root/drivers/char/console.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. gotoxy
  2. __set_origin
  3. scrollback
  4. scrollfront
  5. set_origin
  6. hide_cursor
  7. set_cursor
  8. scrup
  9. scrdown
  10. lf
  11. ri
  12. cr
  13. bs
  14. del
  15. csi_J
  16. csi_K
  17. csi_X
  18. update_attr
  19. default_attr
  20. csi_m
  21. respond_string
  22. cursor_report
  23. mouse_report
  24. status_report
  25. respond_ID
  26. invert_screen
  27. set_mode
  28. setterm_command
  29. insert_char
  30. insert_line
  31. delete_char
  32. delete_line
  33. csi_at
  34. csi_L
  35. csi_P
  36. csi_M
  37. save_cur
  38. restore_cur
  39. reset_terminal
  40. con_stop
  41. con_start
  42. con_write
  43. con_write_room
  44. con_chars_in_buffer
  45. poke_blanked_console
  46. memsetw
  47. console_print
  48. con_throttle
  49. con_unthrottle
  50. con_init
  51. kbdsave
  52. get_scrmem
  53. set_scrmem
  54. blank_screen
  55. unblank_screen
  56. update_screen
  57. do_screendump
  58. con_open
  59. highlight
  60. highlight_pointer
  61. inword
  62. sel_loadlut
  63. atedge
  64. limit
  65. mouse_reporting
  66. set_selection
  67. paste_selection
  68. clear_selection
  69. set_get_font
  70. con_set_font
  71. con_get_font
  72. con_set_trans
  73. con_get_trans

   1 /*
   2  *  linux/kernel/console.c
   3  *
   4  *  Copyright (C) 1991, 1992  Linus Torvalds
   5  */
   6 
   7 /*
   8  *      console.c
   9  *
  10  * This module exports the console io functions:
  11  * 
  12  *      'long con_init(long)'
  13  *      'int con_open(struct tty_struct *tty, struct file * filp)'
  14  *      'void update_screen(int new_console)'
  15  *      'void blank_screen(void)'
  16  *      'void unblank_screen(void)'
  17  *
  18  *      'int  con_get_font(char *)' 
  19  *      'int  con_set_font(char *)' 
  20  *      'int  con_get_trans(char *)'
  21  *      'int  con_set_trans(char *)'
  22  * 
  23  * Hopefully this will be a rather complete VT102 implementation.
  24  *
  25  * Beeping thanks to John T Kohl.
  26  * 
  27  * Virtual Consoles, Screen Blanking, Screen Dumping, Color, Graphics
  28  *   Chars, and VT100 enhancements by Peter MacDonald.
  29  *
  30  * Copy and paste function by Andrew Haylett.
  31  *
  32  * User definable mapping table and font loading by Eugene G. Crosser,
  33  * <crosser@pccross.msk.su>
  34  *
  35  * Code to check for different video-cards mostly by Galen Hunt,
  36  * <g-hunt@ee.utah.edu>
  37  *
  38  * Code for xterm like mouse click reporting by Peter Orbaek 20-Jul-94
  39  * <poe@daimi.aau.dk>
  40  *
  41  */
  42 
  43 #define CAN_LOAD_EGA_FONTS    /* undefine if the user must not do this */
  44 
  45 /*
  46  *  NOTE!!! We sometimes disable and enable interrupts for a short while
  47  * (to put a word in video IO), but this will work even for keyboard
  48  * interrupts. We know interrupts aren't enabled when getting a keyboard
  49  * interrupt, as we use trap-gates. Hopefully all is well.
  50  */
  51 
  52 #include <linux/sched.h>
  53 #include <linux/timer.h>
  54 #include <linux/interrupt.h>
  55 #include <linux/tty.h>
  56 #include <linux/tty_flip.h>
  57 #include <linux/config.h>
  58 #include <linux/kernel.h>
  59 #include <linux/string.h>
  60 #include <linux/errno.h>
  61 #include <linux/kd.h>
  62 #include <linux/major.h>
  63 
  64 #include <asm/io.h>
  65 #include <asm/system.h>
  66 #include <asm/segment.h>
  67 #include <asm/bitops.h>
  68 
  69 #include "kbd_kern.h"
  70 #include "vt_kern.h"
  71 
  72 #ifndef MIN
  73 #define MIN(a,b)        ((a) < (b) ? (a) : (b))
  74 #endif
  75 
  76 struct tty_driver console_driver;
  77 static int console_refcount;
  78 static struct tty_struct *console_table[NR_CONSOLES];
  79 static struct termios *console_termios[NR_CONSOLES];
  80 static struct termios *console_termios_locked[NR_CONSOLES];
  81 
  82 #ifdef CONFIG_SELECTION
  83 #include <linux/ctype.h>
  84 
  85 /* Routines for selection control. */
  86 int set_selection(const int arg, struct tty_struct *tty);
  87 int paste_selection(struct tty_struct *tty);
  88 static void clear_selection(void);
  89 static void highlight_pointer(const int currcons, const int where);
  90 
  91 /* Variables for selection control. */
  92 #define SEL_BUFFER_SIZE 4096
  93 static int sel_cons;
  94 static int sel_start = -1;
  95 static int sel_end;
  96 static char sel_buffer[SEL_BUFFER_SIZE] = { '\0' };
  97 #endif /* CONFIG_SELECTION */
  98 
  99 #define NPAR 16
 100 
 101 extern void vt_init(void);
 102 extern void register_console(void (*proc)(const char *));
 103 extern void compute_shiftstate(void);
 104 
 105 unsigned long   video_num_columns;              /* Number of text columns       */
 106 unsigned long   video_num_lines;                /* Number of text lines         */
 107 
 108 static unsigned char    video_type;             /* Type of display being used   */
 109 static unsigned long    video_mem_base;         /* Base of video memory         */
 110 static unsigned long    video_mem_term;         /* End of video memory          */
 111 static unsigned long    video_size_row;         /* Bytes per row                */
 112 static unsigned char    video_page;             /* Initial video page           */
 113 static unsigned short   video_port_reg;         /* Video register select port   */
 114 static unsigned short   video_port_val;         /* Video register value port    */
 115 static int can_do_color = 0;
 116 static int printable = 0;
 117 
 118 static struct {
 119         unsigned short  vc_video_erase_char;    /* Background erase character */
 120         unsigned char   vc_attr;                /* Current attributes */
 121         unsigned char   vc_def_color;           /* Default colors */
 122         unsigned char   vc_color;               /* Foreground & background */
 123         unsigned char   vc_s_color;             /* Saved foreground & background */
 124         unsigned char   vc_ulcolor;             /* Colour for underline mode */
 125         unsigned char   vc_halfcolor;           /* Colour for half intensity mode */
 126         unsigned long   vc_origin;              /* Used for EGA/VGA fast scroll */
 127         unsigned long   vc_scr_end;             /* Used for EGA/VGA fast scroll */
 128         unsigned long   vc_pos;
 129         unsigned long   vc_x,vc_y;
 130         unsigned long   vc_top,vc_bottom;
 131         unsigned long   vc_state;
 132         unsigned long   vc_npar,vc_par[NPAR];
 133         unsigned long   vc_video_mem_start;     /* Start of video RAM           */
 134         unsigned long   vc_video_mem_end;       /* End of video RAM (sort of)   */
 135         unsigned long   vc_saved_x;
 136         unsigned long   vc_saved_y;
 137         /* mode flags */
 138         unsigned long   vc_charset      : 1;    /* Character set G0 / G1 */
 139         unsigned long   vc_s_charset    : 1;    /* Saved character set */
 140         unsigned long   vc_disp_ctrl    : 1;    /* Display chars < 32? */
 141         unsigned long   vc_toggle_meta  : 1;    /* Toggle high bit? */
 142         unsigned long   vc_decscnm      : 1;    /* Screen Mode */
 143         unsigned long   vc_decom        : 1;    /* Origin Mode */
 144         unsigned long   vc_decawm       : 1;    /* Autowrap Mode */
 145         unsigned long   vc_deccm        : 1;    /* Cursor Visible */
 146         unsigned long   vc_decim        : 1;    /* Insert Mode */
 147         /* attribute flags */
 148         unsigned long   vc_intensity    : 2;    /* 0=half-bright, 1=normal, 2=bold */
 149         unsigned long   vc_underline    : 1;
 150         unsigned long   vc_blink        : 1;
 151         unsigned long   vc_reverse      : 1;
 152         unsigned long   vc_s_intensity  : 2;    /* saved rendition */
 153         unsigned long   vc_s_underline  : 1;
 154         unsigned long   vc_s_blink      : 1;
 155         unsigned long   vc_s_reverse    : 1;
 156         /* misc */
 157         unsigned long   vc_ques         : 1;
 158         unsigned long   vc_need_wrap    : 1;
 159         unsigned long   vc_report_mouse : 2;
 160         unsigned long   vc_tab_stop[5];         /* Tab stops. 160 columns. */
 161         unsigned char * vc_translate;
 162         unsigned char * vc_G0_charset;
 163         unsigned char * vc_G1_charset;
 164         unsigned char * vc_saved_G0;
 165         unsigned char * vc_saved_G1;
 166         /* additional information is in vt_kern.h */
 167 } vc_cons [NR_CONSOLES];
 168 
 169 unsigned short *vc_scrbuf[NR_CONSOLES];
 170 static unsigned short * vc_scrmembuf;
 171 static int console_blanked = 0;
 172 
 173 #define origin          (vc_cons[currcons].vc_origin)
 174 #define scr_end         (vc_cons[currcons].vc_scr_end)
 175 #define pos             (vc_cons[currcons].vc_pos)
 176 #define top             (vc_cons[currcons].vc_top)
 177 #define bottom          (vc_cons[currcons].vc_bottom)
 178 #define x               (vc_cons[currcons].vc_x)
 179 #define y               (vc_cons[currcons].vc_y)
 180 #define vc_state                (vc_cons[currcons].vc_state)
 181 #define npar            (vc_cons[currcons].vc_npar)
 182 #define par             (vc_cons[currcons].vc_par)
 183 #define ques            (vc_cons[currcons].vc_ques)
 184 #define attr            (vc_cons[currcons].vc_attr)
 185 #define saved_x         (vc_cons[currcons].vc_saved_x)
 186 #define saved_y         (vc_cons[currcons].vc_saved_y)
 187 #define translate       (vc_cons[currcons].vc_translate)
 188 #define G0_charset      (vc_cons[currcons].vc_G0_charset)
 189 #define G1_charset      (vc_cons[currcons].vc_G1_charset)
 190 #define saved_G0        (vc_cons[currcons].vc_saved_G0)
 191 #define saved_G1        (vc_cons[currcons].vc_saved_G1)
 192 #define video_mem_start (vc_cons[currcons].vc_video_mem_start)
 193 #define video_mem_end   (vc_cons[currcons].vc_video_mem_end)
 194 #define video_erase_char (vc_cons[currcons].vc_video_erase_char)        
 195 #define disp_ctrl       (vc_cons[currcons].vc_disp_ctrl)
 196 #define toggle_meta     (vc_cons[currcons].vc_toggle_meta)
 197 #define decscnm         (vc_cons[currcons].vc_decscnm)
 198 #define decom           (vc_cons[currcons].vc_decom)
 199 #define decawm          (vc_cons[currcons].vc_decawm)
 200 #define deccm           (vc_cons[currcons].vc_deccm)
 201 #define decim           (vc_cons[currcons].vc_decim)
 202 #define need_wrap       (vc_cons[currcons].vc_need_wrap)
 203 #define report_mouse    (vc_cons[currcons].vc_report_mouse)
 204 #define color           (vc_cons[currcons].vc_color)
 205 #define s_color         (vc_cons[currcons].vc_s_color)
 206 #define def_color       (vc_cons[currcons].vc_def_color)
 207 #define foreground      (color & 0x0f)
 208 #define background      (color & 0xf0)
 209 #define charset         (vc_cons[currcons].vc_charset)
 210 #define s_charset       (vc_cons[currcons].vc_s_charset)
 211 #define intensity       (vc_cons[currcons].vc_intensity)
 212 #define underline       (vc_cons[currcons].vc_underline)
 213 #define blink           (vc_cons[currcons].vc_blink)
 214 #define reverse         (vc_cons[currcons].vc_reverse)
 215 #define s_intensity     (vc_cons[currcons].vc_s_intensity)
 216 #define s_underline     (vc_cons[currcons].vc_s_underline)
 217 #define s_blink         (vc_cons[currcons].vc_s_blink)
 218 #define s_reverse       (vc_cons[currcons].vc_s_reverse)
 219 #define ulcolor         (vc_cons[currcons].vc_ulcolor)
 220 #define halfcolor       (vc_cons[currcons].vc_halfcolor)
 221 #define tab_stop        (vc_cons[currcons].vc_tab_stop)
 222 #define vcmode          (vt_cons[currcons].vc_mode)
 223 #define vtmode          (vt_cons[currcons].vt_mode)
 224 #define vtpid           (vt_cons[currcons].vt_pid)
 225 #define vtnewvt         (vt_cons[currcons].vt_newvt)
 226 
 227 #define set_kbd(x) set_vc_kbd_mode(kbd_table+currcons,x)
 228 #define clr_kbd(x) clr_vc_kbd_mode(kbd_table+currcons,x)
 229 #define is_kbd(x) vc_kbd_mode(kbd_table+currcons,x)
 230 
 231 #define decarm          VC_REPEAT
 232 #define decckm          VC_CKMODE
 233 #define kbdapplic       VC_APPLIC
 234 #define kbdraw          VC_RAW
 235 #define lnm             VC_CRLF
 236 
 237 int blankinterval = 10*60*HZ;
 238 static int screen_size = 0;
 239 
 240 /*
 241  * this is what the terminal answers to a ESC-Z or csi0c query.
 242  */
 243 #define VT100ID "\033[?1;2c"
 244 #define VT102ID "\033[?6c"
 245 
 246 static unsigned char * translations[] = {
 247 /* 8-bit Latin-1 mapped to the PC character set: '\0' means non-printable */
 248 (unsigned char *)
 249         "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
 250         "\0\0\0\0\0\0\0\0\0\0\376\0\0\0\0\0"
 251         " !\"#$%&'()*+,-./0123456789:;<=>?"
 252         "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
 253         "`abcdefghijklmnopqrstuvwxyz{|}~\0"
 254         "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
 255         "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
 256         "\377\255\233\234\376\235\174\025\376\376\246\256\252\055\376\376"
 257         "\370\361\375\376\376\346\024\371\376\376\247\257\254\253\376\250"
 258         "\376\376\376\376\216\217\222\200\376\220\376\376\376\376\376\376"
 259         "\376\245\376\376\376\376\231\376\350\376\376\376\232\376\376\341"
 260         "\205\240\203\376\204\206\221\207\212\202\210\211\215\241\214\213"
 261         "\376\244\225\242\223\376\224\366\355\227\243\226\201\376\376\230",
 262 /* vt100 graphics */
 263 (unsigned char *)
 264         "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
 265         "\0\0\0\0\0\0\0\0\0\0\376\0\0\0\0\0"
 266         " !\"#$%&'()*+,-./0123456789:;<=>?"
 267         "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^ "
 268         "\004\261\007\007\007\007\370\361\007\007\331\277\332\300\305\304"
 269         "\304\304\137\137\303\264\301\302\263\363\362\343\330\234\007\0"
 270         "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
 271         "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
 272         "\377\255\233\234\376\235\174\025\376\376\246\256\252\055\376\376"
 273         "\370\361\375\376\376\346\024\371\376\376\247\257\254\253\376\250"
 274         "\376\376\376\376\216\217\222\200\376\220\376\376\376\376\376\376"
 275         "\376\245\376\376\376\376\231\376\376\376\376\376\232\376\376\341"
 276         "\205\240\203\376\204\206\221\207\212\202\210\211\215\241\214\213"
 277         "\376\244\225\242\223\376\224\366\376\227\243\226\201\376\376\230",
 278 /* IBM graphics: minimal translations (BS, CR, LF, LL, SO, SI and ESC) */
 279 (unsigned char *)
 280         "\000\001\002\003\004\005\006\007\000\011\000\013\000\000\000\000"
 281         "\020\021\022\023\024\025\026\027\030\031\032\000\034\035\036\037"
 282         "\040\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057"
 283         "\060\061\062\063\064\065\066\067\070\071\072\073\074\075\076\077"
 284         "\100\101\102\103\104\105\106\107\110\111\112\113\114\115\116\117"
 285         "\120\121\122\123\124\125\126\127\130\131\132\133\134\135\136\137"
 286         "\140\141\142\143\144\145\146\147\150\151\152\153\154\155\156\157"
 287         "\160\161\162\163\164\165\166\167\170\171\172\173\174\175\176\177"
 288         "\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217"
 289         "\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237"
 290         "\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257"
 291         "\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277"
 292         "\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317"
 293         "\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337"
 294         "\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357"
 295         "\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377",
 296  /* USER: customizable mappings, initialized as the previous one (IBM) */
 297 (unsigned char *)
 298         "\000\001\002\003\004\005\006\007\010\011\000\013\000\000\016\017"
 299         "\020\021\022\023\024\025\026\027\030\031\032\000\034\035\036\037"
 300         "\040\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057"
 301         "\060\061\062\063\064\065\066\067\070\071\072\073\074\075\076\077"
 302         "\100\101\102\103\104\105\106\107\110\111\112\113\114\115\116\117"
 303         "\120\121\122\123\124\125\126\127\130\131\132\133\134\135\136\137"
 304         "\140\141\142\143\144\145\146\147\150\151\152\153\154\155\156\157"
 305         "\160\161\162\163\164\165\166\167\170\171\172\173\174\175\176\177"
 306         "\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217"
 307         "\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237"
 308         "\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257"
 309         "\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277"
 310         "\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317"
 311         "\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337"
 312         "\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357"
 313         "\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377"
 314 };
 315 
 316 #define NORM_TRANS (translations[0])
 317 #define GRAF_TRANS (translations[1])
 318 #define NULL_TRANS (translations[2])
 319 #define USER_TRANS (translations[3])
 320 
 321 static unsigned char color_table[] = { 0, 4, 2, 6, 1, 5, 3, 7,
 322                                        8,12,10,14, 9,13,11,15 };
 323 
 324 /*
 325  * gotoxy() must verify all boundaries, because the arguments
 326  * might also be negative. If the given position is out of
 327  * bounds, the cursor is placed at the nearest margin.
 328  */
 329 static void gotoxy(int currcons, int new_x, int new_y)
     /* [previous][next][first][last][top][bottom][index][help] */
 330 {
 331         int max_y;
 332 
 333         if (new_x < 0)
 334                 x = 0;
 335         else
 336                 if (new_x >= video_num_columns)
 337                         x = video_num_columns - 1;
 338                 else
 339                         x = new_x;
 340         if (decom) {
 341                 new_y += top;
 342                 max_y = bottom;
 343         } else
 344                 max_y = video_num_lines;
 345         if (new_y < 0)
 346                 y = 0;
 347         else
 348                 if (new_y >= max_y)
 349                         y = max_y - 1;
 350                 else
 351                         y = new_y;
 352         pos = origin + y*video_size_row + (x<<1);
 353         need_wrap = 0;
 354 }
 355 
 356 /*
 357  * *Very* limited hardware scrollback support..
 358  */
 359 static unsigned short __real_origin;
 360 static unsigned short __origin;
 361 
 362 static inline void __set_origin(unsigned short offset)
     /* [previous][next][first][last][top][bottom][index][help] */
 363 {
 364         unsigned long flags;
 365 #ifdef CONFIG_SELECTION
 366         clear_selection();
 367 #endif /* CONFIG_SELECTION */
 368         save_flags(flags); cli();
 369         __origin = offset;
 370         outb_p(12, video_port_reg);
 371         outb_p(offset >> 8, video_port_val);
 372         outb_p(13, video_port_reg);
 373         outb_p(offset, video_port_val);
 374         restore_flags(flags);
 375 }
 376 
 377 void scrollback(int lines)
     /* [previous][next][first][last][top][bottom][index][help] */
 378 {
 379         if (!lines)
 380                 lines = video_num_lines/2;
 381         lines *= video_num_columns;
 382         lines = __origin - lines;
 383         if (lines < 0)
 384                 lines = 0;
 385         __set_origin(lines);
 386 }
 387 
 388 void scrollfront(int lines)
     /* [previous][next][first][last][top][bottom][index][help] */
 389 {
 390         if (!lines)
 391                 lines = video_num_lines/2;
 392         lines *= video_num_columns;
 393         lines = __origin + lines;
 394         if (lines > __real_origin)
 395                 lines = __real_origin;
 396         __set_origin(lines);
 397 }
 398 
 399 static void set_origin(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 400 {
 401         if (video_type != VIDEO_TYPE_EGAC && video_type != VIDEO_TYPE_EGAM)
 402                 return;
 403         if (currcons != fg_console || console_blanked || vcmode == KD_GRAPHICS)
 404                 return;
 405         __real_origin = (origin-video_mem_base) >> 1;
 406         __set_origin(__real_origin);
 407 }
 408 
 409 /*
 410  * Put the cursor just beyond the end of the display adaptor memory.
 411  */
 412 static inline void hide_cursor(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 413 {
 414   /* This is inefficient, we could just put the cursor at 0xffff,
 415      but perhaps the delays due to the inefficiency are useful for
 416      some hardware... */
 417         outb_p(14, video_port_reg);
 418         outb_p(0xff&((video_mem_term-video_mem_base)>>9), video_port_val);
 419         outb_p(15, video_port_reg);
 420         outb_p(0xff&((video_mem_term-video_mem_base)>>1), video_port_val);
 421 }
 422 
 423 static inline void set_cursor(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 424 {
 425         unsigned long flags;
 426 
 427         if (currcons != fg_console || console_blanked || vcmode == KD_GRAPHICS)
 428                 return;
 429         if (__real_origin != __origin)
 430                 set_origin(__real_origin);
 431         save_flags(flags); cli();
 432         if (deccm) {
 433                 outb_p(14, video_port_reg);
 434                 outb_p(0xff&((pos-video_mem_base)>>9), video_port_val);
 435                 outb_p(15, video_port_reg);
 436                 outb_p(0xff&((pos-video_mem_base)>>1), video_port_val);
 437         } else
 438                 hide_cursor();
 439         restore_flags(flags);
 440 }
 441 
 442 static void scrup(int currcons, unsigned int t, unsigned int b)
     /* [previous][next][first][last][top][bottom][index][help] */
 443 {
 444         int hardscroll = 1;
 445 
 446         if (b > video_num_lines || t >= b)
 447                 return;
 448         if (video_type != VIDEO_TYPE_EGAC && video_type != VIDEO_TYPE_EGAM)
 449                 hardscroll = 0;
 450         else if (t || b != video_num_lines)
 451                 hardscroll = 0;
 452         if (hardscroll) {
 453                 origin += video_size_row;
 454                 pos += video_size_row;
 455                 scr_end += video_size_row;
 456                 if (scr_end > video_mem_end) {
 457                         __asm__("cld\n\t"
 458                                 "rep\n\t"
 459                                 "movsl\n\t"
 460                                 "movl _video_num_columns,%1\n\t"
 461                                 "rep\n\t"
 462                                 "stosw"
 463                                 : /* no output */
 464                                 :"a" (video_erase_char),
 465                                 "c" ((video_num_lines-1)*video_num_columns>>1),
 466                                 "D" (video_mem_start),
 467                                 "S" (origin)
 468                                 :"cx","di","si");
 469                         scr_end -= origin-video_mem_start;
 470                         pos -= origin-video_mem_start;
 471                         origin = video_mem_start;
 472                 } else {
 473                         __asm__("cld\n\t"
 474                                 "rep\n\t"
 475                                 "stosw"
 476                                 : /* no output */
 477                                 :"a" (video_erase_char),
 478                                 "c" (video_num_columns),
 479                                 "D" (scr_end-video_size_row)
 480                                 :"cx","di");
 481                 }
 482                 set_origin(currcons);
 483         } else {
 484                 __asm__("cld\n\t"
 485                         "rep\n\t"
 486                         "movsl\n\t"
 487                         "movl _video_num_columns,%%ecx\n\t"
 488                         "rep\n\t"
 489                         "stosw"
 490                         : /* no output */
 491                         :"a" (video_erase_char),
 492                         "c" ((b-t-1)*video_num_columns>>1),
 493                         "D" (origin+video_size_row*t),
 494                         "S" (origin+video_size_row*(t+1))
 495                         :"cx","di","si");
 496         }
 497 }
 498 
 499 static void scrdown(int currcons, unsigned int t, unsigned int b)
     /* [previous][next][first][last][top][bottom][index][help] */
 500 {
 501         if (b > video_num_lines || t >= b)
 502                 return;
 503         __asm__("std\n\t"
 504                 "rep\n\t"
 505                 "movsl\n\t"
 506                 "addl $2,%%edi\n\t"     /* %edi has been decremented by 4 */
 507                 "movl _video_num_columns,%%ecx\n\t"
 508                 "rep\n\t"
 509                 "stosw\n\t"
 510                 "cld"
 511                 : /* no output */
 512                 :"a" (video_erase_char),
 513                 "c" ((b-t-1)*video_num_columns>>1),
 514                 "D" (origin+video_size_row*b-4),
 515                 "S" (origin+video_size_row*(b-1)-4)
 516                 :"ax","cx","di","si");
 517 }
 518 
 519 static void lf(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 520 {
 521         if (y+1<bottom) {
 522                 y++;
 523                 pos += video_size_row;
 524                 return;
 525         } else 
 526                 scrup(currcons,top,bottom);
 527         need_wrap = 0;
 528 }
 529 
 530 static void ri(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 531 {
 532         if (y>top) {
 533                 y--;
 534                 pos -= video_size_row;
 535                 return;
 536         } else
 537                 scrdown(currcons,top,bottom);
 538         need_wrap = 0;
 539 }
 540 
 541 static inline void cr(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 542 {
 543         pos -= x<<1;
 544         need_wrap = x = 0;
 545 }
 546 
 547 static inline void bs(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 548 {
 549         if (x) {
 550                 pos -= 2;
 551                 x--;
 552                 need_wrap = 0;
 553         }
 554 }
 555 
 556 static inline void del(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 557 {
 558 #if 0
 559         if (x) {
 560                 if (!need_wrap) {    /* this is not the right condition */
 561                         pos -= 2;
 562                         x--;
 563                 }
 564                 *(unsigned short *)pos = video_erase_char;
 565                 need_wrap = 0;
 566         }
 567 #endif
 568 }
 569 
 570 static void csi_J(int currcons, int vpar)
     /* [previous][next][first][last][top][bottom][index][help] */
 571 {
 572         unsigned long count;
 573         unsigned long start;
 574 
 575         switch (vpar) {
 576                 case 0: /* erase from cursor to end of display */
 577                         count = (scr_end-pos)>>1;
 578                         start = pos;
 579                         break;
 580                 case 1: /* erase from start to cursor */
 581                         count = ((pos-origin)>>1)+1;
 582                         start = origin;
 583                         break;
 584                 case 2: /* erase whole display */
 585                         count = video_num_columns * video_num_lines;
 586                         start = origin;
 587                         break;
 588                 default:
 589                         return;
 590         }
 591         __asm__("cld\n\t"
 592                 "rep\n\t"
 593                 "stosw\n\t"
 594                 : /* no output */
 595                 :"c" (count),
 596                 "D" (start),"a" (video_erase_char)
 597                 :"cx","di");
 598         need_wrap = 0;
 599 }
 600 
 601 static void csi_K(int currcons, int vpar)
     /* [previous][next][first][last][top][bottom][index][help] */
 602 {
 603         long count;
 604         long start;
 605 
 606         switch (vpar) {
 607                 case 0: /* erase from cursor to end of line */
 608                         count = video_num_columns-x;
 609                         start = pos;
 610                         break;
 611                 case 1: /* erase from start of line to cursor */
 612                         start = pos - (x<<1);
 613                         count = x+1;
 614                         break;
 615                 case 2: /* erase whole line */
 616                         start = pos - (x<<1);
 617                         count = video_num_columns;
 618                         break;
 619                 default:
 620                         return;
 621         }
 622         __asm__("cld\n\t"
 623                 "rep\n\t"
 624                 "stosw\n\t"
 625                 : /* no output */
 626                 :"c" (count),
 627                 "D" (start),"a" (video_erase_char)
 628                 :"cx","di");
 629         need_wrap = 0;
 630 }
 631 
 632 static void csi_X(int currcons, int vpar)
     /* [previous][next][first][last][top][bottom][index][help] */
 633 {
 634         long count;
 635         long start;
 636 
 637         if (!vpar)
 638                 vpar++;
 639 
 640         start=pos;
 641         count=(vpar > video_num_columns-x) ? (video_num_columns-x) : vpar;
 642 
 643         __asm__("cld\n\t"
 644                 "rep\n\t"
 645                 "stosw\n\t"
 646                 : /* no output */
 647                 :"c" (count),
 648                 "D" (start),"a" (video_erase_char)
 649                 :"cx","di");
 650         need_wrap = 0;
 651 }
 652 
 653 /*
 654  *  I hope this works. The monochrome part is untested.
 655  */
 656 static void update_attr(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 657 {
 658         attr = color;
 659         if (can_do_color) {
 660                 if (underline)
 661                         attr = (attr & 0xf0) | ulcolor;
 662                 else if (intensity == 0)
 663                         attr = (attr & 0xf0) | halfcolor;
 664         }
 665         if (reverse ^ decscnm)
 666                 attr = (attr & 0x88) | (((attr >> 4) | (attr << 4)) & 0x77);
 667         if (blink)
 668                 attr ^= 0x80;
 669         if (intensity == 2)
 670                 attr ^= 0x08;
 671         if (!can_do_color) {
 672                 if (underline)
 673                         attr = (attr & 0xf8) | 0x01;
 674                 else if (intensity == 0)
 675                         attr = (attr & 0xf0) | 0x08;
 676         }
 677         if (decscnm)
 678                 video_erase_char = (((color & 0x88) | (((color >> 4) | (color << 4)) & 0x77)) << 8) | ' ';
 679         else
 680                 video_erase_char = (color << 8) | ' ';
 681 }
 682 
 683 static void default_attr(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 684 {
 685         intensity = 1;
 686         underline = 0;
 687         reverse = 0;
 688         blink = 0;
 689         color = def_color;
 690 }
 691 
 692 static void csi_m(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 693 {
 694         int i;
 695 
 696         for (i=0;i<=npar;i++)
 697                 switch (par[i]) {
 698                         case 0: /* all attributes off */
 699                                 default_attr(currcons);
 700                                 break;
 701                         case 1:
 702                                 intensity = 2;
 703                                 break;
 704                         case 2:
 705                                 intensity = 0;
 706                                 break;
 707                         case 4:
 708                                 underline = 1;
 709                                 break;
 710                         case 5:
 711                                 blink = 1;
 712                                 break;
 713                         case 7:
 714                                 reverse = 1;
 715                                 break;
 716                         case 10: /* ANSI X3.64-1979 (SCO-ish?)
 717                                   * Select primary font, don't display
 718                                   * control chars if defined, don't set
 719                                   * bit 8 on output.
 720                                   */
 721                                 translate = (charset == 0
 722                                                 ? G0_charset
 723                                                 : G1_charset);
 724                                 disp_ctrl = 0;
 725                                 toggle_meta = 0;
 726                                 break;
 727                         case 11: /* ANSI X3.64-1979 (SCO-ish?)
 728                                   * Select first alternate font, let's
 729                                   * chars < 32 be displayed as ROM chars.
 730                                   */
 731                                 translate = NULL_TRANS;
 732                                 disp_ctrl = 1;
 733                                 toggle_meta = 0;
 734                                 break;
 735                         case 12: /* ANSI X3.64-1979 (SCO-ish?)
 736                                   * Select second alternate font, toggle
 737                                   * high bit before displaying as ROM char.
 738                                   */
 739                                 translate = NULL_TRANS;
 740                                 disp_ctrl = 1;
 741                                 toggle_meta = 1;
 742                                 break;
 743                         case 21:
 744                         case 22:
 745                                 intensity = 1;
 746                                 break;
 747                         case 24:
 748                                 underline = 0;
 749                                 break;
 750                         case 25:
 751                                 blink = 0;
 752                                 break;
 753                         case 27:
 754                                 reverse = 0;
 755                                 break;
 756                         case 38: /* ANSI X3.64-1979 (SCO-ish?)
 757                                   * Enables underscore, white foreground
 758                                   * with white underscore (Linux - use
 759                                   * default foreground).
 760                                   */
 761                                 color = (def_color & 0x0f) | background;
 762                                 underline = 1;
 763                                 break;
 764                         case 39: /* ANSI X3.64-1979 (SCO-ish?)
 765                                   * Disable underline option.
 766                                   * Reset colour to default? It did this
 767                                   * before...
 768                                   */
 769                                 color = (def_color & 0x0f) | background;
 770                                 underline = 0;
 771                                 break;
 772                         case 49:
 773                                 color = (def_color & 0xf0) | foreground;
 774                                 break;
 775                         default:
 776                                 if (par[i] >= 30 && par[i] <= 37)
 777                                         color = color_table[par[i]-30]
 778                                                 | background; 
 779                                 else if (par[i] >= 40 && par[i] <= 47)
 780                                         color = (color_table[par[i]-40]<<4)
 781                                                 | foreground;
 782                                 break;
 783                 }
 784         update_attr(currcons);
 785 }
 786 
 787 static void respond_string(char * p, struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 788 {
 789         while (*p) {
 790                 tty_insert_flip_char(tty, *p, 0);
 791                 p++;
 792         }
 793         tty_schedule_flip(tty);
 794 }
 795 
 796 static void cursor_report(int currcons, struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 797 {
 798         char buf[40];
 799 
 800         sprintf(buf, "\033[%ld;%ldR", y + (decom ? top+1 : 1), x+1);
 801         respond_string(buf, tty);
 802 }
 803 
 804 static void mouse_report(int currcons, struct tty_struct * tty,
     /* [previous][next][first][last][top][bottom][index][help] */
 805                          int butt, int mrx, int mry)
 806 {
 807         char buf[8];
 808 
 809         sprintf(buf, "\033[M%c%c%c", (char)(' ' + butt), (char)('!' + mrx),
 810                 (char)('!' + mry));
 811         respond_string(buf, tty);
 812 }
 813 
 814 static inline void status_report(int currcons, struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 815 {
 816         respond_string("\033[0n", tty); /* Terminal ok */
 817 }
 818 
 819 static inline void respond_ID(int currcons, struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 820 {
 821         respond_string(VT102ID, tty);
 822 }
 823 
 824 static void invert_screen(int currcons) {
     /* [previous][next][first][last][top][bottom][index][help] */
 825         unsigned char *p;
 826 
 827         if (can_do_color)
 828                 for (p = (unsigned char *)origin+1; p < (unsigned char *)scr_end; p+=2)
 829                         *p = (*p & 0x88) | (((*p >> 4) | (*p << 4)) & 0x77);
 830         else
 831                 for (p = (unsigned char *)origin+1; p < (unsigned char *)scr_end; p+=2)
 832                         *p ^= *p & 0x07 == 1 ? 0x70 : 0x77;
 833 }
 834 
 835 static void set_mode(int currcons, int on_off)
     /* [previous][next][first][last][top][bottom][index][help] */
 836 {
 837         int i;
 838 
 839         for (i=0; i<=npar; i++)
 840                 if (ques) switch(par[i]) {      /* DEC private modes set/reset */
 841                         case 1:                 /* Cursor keys send ^[Ox/^[[x */
 842                                 if (on_off)
 843                                         set_kbd(decckm);
 844                                 else
 845                                         clr_kbd(decckm);
 846                                 break;
 847                         case 3: /* 80/132 mode switch unimplemented */
 848                                 csi_J(currcons,2);
 849                                 gotoxy(currcons,0,0);
 850                                 break;
 851                         case 5:                 /* Inverted screen on/off */
 852                                 if (decscnm != on_off) {
 853                                         decscnm = on_off;
 854                                         invert_screen(currcons);
 855                                         update_attr(currcons);
 856                                 }
 857                                 break;
 858                         case 6:                 /* Origin relative/absolute */
 859                                 decom = on_off;
 860                                 gotoxy(currcons,0,0);
 861                                 break;
 862                         case 7:                 /* Autowrap on/off */
 863                                 decawm = on_off;
 864                                 break;
 865                         case 8:                 /* Autorepeat on/off */
 866                                 if (on_off)
 867                                         set_kbd(decarm);
 868                                 else
 869                                         clr_kbd(decarm);
 870                                 break;
 871                         case 9:
 872                                 report_mouse = on_off ? 1 : 0;
 873                                 break;
 874                         case 25:                /* Cursor on/off */
 875                                 deccm = on_off;
 876                                 set_cursor(currcons);
 877                                 break;
 878                         case 1000:
 879                                 report_mouse = on_off ? 2 : 0;
 880                                 break;
 881                 } else switch(par[i]) {         /* ANSI modes set/reset */
 882                         case 4:                 /* Insert Mode on/off */
 883                                 decim = on_off;
 884                                 break;
 885                         case 20:                /* Lf, Enter == CrLf/Lf */
 886                                 if (on_off)
 887                                         set_kbd(lnm);
 888                                 else
 889                                         clr_kbd(lnm);
 890                                 break;
 891                 }
 892 }
 893 
 894 static void setterm_command(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 895 {
 896         switch(par[0]) {
 897                 case 1: /* set color for underline mode */
 898                         if (can_do_color && par[1] < 16) {
 899                                 ulcolor = color_table[par[1]];
 900                                 if (underline)
 901                                         update_attr(currcons);
 902                         }
 903                         break;
 904                 case 2: /* set color for half intensity mode */
 905                         if (can_do_color && par[1] < 16) {
 906                                 halfcolor = color_table[par[1]];
 907                                 if (intensity == 0)
 908                                         update_attr(currcons);
 909                         }
 910                         break;
 911                 case 8: /* store colors as defaults */
 912                         def_color = attr;
 913                         default_attr(currcons);
 914                         update_attr(currcons);
 915                         break;
 916                 case 9: /* set blanking interval */
 917                         blankinterval = ((par[1] < 60) ? par[1] : 60) * 60 * HZ;
 918                         break;
 919         }
 920 }
 921 
 922 static void insert_char(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 923 {
 924         unsigned int i = x;
 925         unsigned short tmp, old = video_erase_char;
 926         unsigned short * p = (unsigned short *) pos;
 927 
 928         while (i++ < video_num_columns) {
 929                 tmp = *p;
 930                 *p = old;
 931                 old = tmp;
 932                 p++;
 933         }
 934         need_wrap = 0;
 935 }
 936 
 937 static void insert_line(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 938 {
 939         scrdown(currcons,y,bottom);
 940         need_wrap = 0;
 941 }
 942 
 943 static void delete_char(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 944 {
 945         unsigned int i = x;
 946         unsigned short * p = (unsigned short *) pos;
 947 
 948         while (++i < video_num_columns) {
 949                 *p = *(p+1);
 950                 p++;
 951         }
 952         *p = video_erase_char;
 953         need_wrap = 0;
 954 }
 955 
 956 static void delete_line(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 957 {
 958         scrup(currcons,y,bottom);
 959         need_wrap = 0;
 960 }
 961 
 962 static void csi_at(int currcons, unsigned int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
 963 {
 964         if (nr > video_num_columns)
 965                 nr = video_num_columns;
 966         else if (!nr)
 967                 nr = 1;
 968         while (nr--)
 969                 insert_char(currcons);
 970 }
 971 
 972 static void csi_L(int currcons, unsigned int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
 973 {
 974         if (nr > video_num_lines)
 975                 nr = video_num_lines;
 976         else if (!nr)
 977                 nr = 1;
 978         while (nr--)
 979                 insert_line(currcons);
 980 }
 981 
 982 static void csi_P(int currcons, unsigned int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
 983 {
 984         if (nr > video_num_columns)
 985                 nr = video_num_columns;
 986         else if (!nr)
 987                 nr = 1;
 988         while (nr--)
 989                 delete_char(currcons);
 990 }
 991 
 992 static void csi_M(int currcons, unsigned int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
 993 {
 994         if (nr > video_num_lines)
 995                 nr = video_num_lines;
 996         else if (!nr)
 997                 nr=1;
 998         while (nr--)
 999                 delete_line(currcons);
1000 }
1001 
1002 static void save_cur(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
1003 {
1004         saved_x         = x;
1005         saved_y         = y;
1006         s_intensity     = intensity;
1007         s_underline     = underline;
1008         s_blink         = blink;
1009         s_reverse       = reverse;
1010         s_charset       = charset;
1011         s_color         = color;
1012         saved_G0        = G0_charset;
1013         saved_G1        = G1_charset;
1014 }
1015 
1016 static void restore_cur(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
1017 {
1018         gotoxy(currcons,saved_x,saved_y);
1019         intensity       = s_intensity;
1020         underline       = s_underline;
1021         blink           = s_blink;
1022         reverse         = s_reverse;
1023         charset         = s_charset;
1024         color           = s_color;
1025         G0_charset      = saved_G0;
1026         G1_charset      = saved_G1;
1027         translate       = charset ? G1_charset : G0_charset;
1028         update_attr(currcons);
1029         need_wrap = 0;
1030 }
1031 
1032 enum { ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey, 
1033         EShash, ESsetG0, ESsetG1, ESignore };
1034 
1035 static void reset_terminal(int currcons, int do_clear)
     /* [previous][next][first][last][top][bottom][index][help] */
1036 {
1037         top             = 0;
1038         bottom          = video_num_lines;
1039         vc_state                = ESnormal;
1040         ques            = 0;
1041         translate       = NORM_TRANS;
1042         G0_charset      = NORM_TRANS;
1043         G1_charset      = GRAF_TRANS;
1044         charset         = 0;
1045         need_wrap       = 0;
1046         report_mouse    = 0;
1047 
1048         disp_ctrl       = 0;
1049         toggle_meta     = 0;
1050 
1051         decscnm         = 0;
1052         decom           = 0;
1053         decawm          = 1;
1054         deccm           = 1;
1055         decim           = 0;
1056 
1057         set_kbd(decarm);
1058         clr_kbd(decckm);
1059         clr_kbd(kbdapplic);
1060         clr_kbd(lnm);
1061         kbd_table[currcons].lockstate = 0;
1062         kbd_table[currcons].ledstate = kbd_table[currcons].default_ledstate;
1063         set_leds();
1064 
1065         default_attr(currcons);
1066         update_attr(currcons);
1067 
1068         tab_stop[0]     = 0x01010100;
1069         tab_stop[1]     =
1070         tab_stop[2]     =
1071         tab_stop[3]     =
1072         tab_stop[4]     = 0x01010101;
1073 
1074         if (do_clear) {
1075                 gotoxy(currcons,0,0);
1076                 csi_J(currcons,2);
1077                 save_cur(currcons);
1078         }
1079 }
1080 
1081 /*
1082  * Turn the Scroll-Lock LED on when the tty is stopped (with a ^S)
1083  */
1084 static void con_stop(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
1085 {
1086         set_vc_kbd_led(kbd_table + fg_console, VC_SCROLLOCK);
1087         set_leds();
1088 }
1089 
1090 /*
1091  * Turn the Scroll-Lock LED off when the console is started (with a ^Q)
1092  */
1093 static void con_start(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
1094 {
1095         clr_vc_kbd_led(kbd_table + fg_console, VC_SCROLLOCK);
1096         set_leds();
1097 }
1098 
1099 static int con_write(struct tty_struct * tty, int from_user,
     /* [previous][next][first][last][top][bottom][index][help] */
1100                      unsigned char *buf, int count)
1101 {
1102         int c, n = 0;
1103         unsigned int currcons;
1104         struct vt_struct *vt = tty->driver_data;
1105 
1106         currcons = vt->vc_num;
1107         if (currcons >= NR_CONSOLES) {
1108                 printk("con_write: illegal vc index (%d)\n", currcons);
1109                 return 0;
1110         }
1111 #ifdef CONFIG_SELECTION
1112         /* clear the selection */
1113         if (currcons == sel_cons)
1114                 clear_selection();
1115 #endif /* CONFIG_SELECTION */
1116         disable_bh(KEYBOARD_BH);
1117         while (!tty->stopped && count) {
1118                 c = from_user ? get_fs_byte(buf) : *buf;
1119                 buf++; n++; count--;
1120                 if (vc_state == ESnormal
1121                 && (c >= 32 || (disp_ctrl && (c&0x7f) != 27))
1122                 && (toggle_meta ? translate[c|0x80] : translate[c])) {
1123                         if (toggle_meta)
1124                                 c |= 0x80;
1125                         if (need_wrap) {
1126                                 cr(currcons);
1127                                 lf(currcons);
1128                         }
1129                         if (decim)
1130                                 insert_char(currcons);
1131                         c = translate[c];
1132                         *(unsigned short *) pos = (attr << 8) + c;
1133                         if (x == video_num_columns - 1)
1134                                 need_wrap = decawm;
1135                         else {
1136                                 x++;
1137                                 pos+=2;
1138                         }
1139                         continue;
1140                 }
1141 
1142                 /*
1143                  *  Control characters can be used in the _middle_
1144                  *  of an escape sequence.
1145                  */
1146                 switch (c) {
1147                         case 7:
1148                                 kd_mksound(0x637, HZ/8);
1149                                 continue;
1150                         case 8:
1151                                 bs(currcons);
1152                                 continue;
1153                         case 9:
1154                                 pos -= (x << 1);
1155                                 while (x < video_num_columns - 1) {
1156                                         x++;
1157                                         if (tab_stop[x >> 5] & (1 << (x & 31)))
1158                                                 break;
1159                                 }
1160                                 pos += (x << 1);
1161                                 continue;
1162                         case 10: case 11: case 12:
1163                                 lf(currcons);
1164                                 if (!is_kbd(lnm))
1165                                         continue;
1166                         case 13:
1167                                 cr(currcons);
1168                                 continue;
1169                         case 14:
1170                                 charset = 1;
1171                                 translate = G1_charset;
1172                                 continue;
1173                         case 15:
1174                                 charset = 0;
1175                                 translate = G0_charset;
1176                                 continue;
1177                         case 24: case 26:
1178                                 vc_state = ESnormal;
1179                                 continue;
1180                         case 27:
1181                                 vc_state = ESesc;
1182                                 continue;
1183                         case 127:
1184                                 del(currcons);
1185                                 continue;
1186                         case 128+27:
1187                                 vc_state = ESsquare;
1188                                 continue;
1189                 }
1190                 switch(vc_state) {
1191                         case ESesc:
1192                                 vc_state = ESnormal;
1193                                 switch (c) {
1194                                   case '[':
1195                                         vc_state = ESsquare;
1196                                         continue;
1197                                   case 'E':
1198                                         cr(currcons);
1199                                         lf(currcons);
1200                                         continue;
1201                                   case 'M':
1202                                         ri(currcons);
1203                                         continue;
1204                                   case 'D':
1205                                         lf(currcons);
1206                                         continue;
1207                                   case 'H':
1208                                         tab_stop[x >> 5] |= (1 << (x & 31));
1209                                         continue;
1210                                   case 'Z':
1211                                         respond_ID(currcons,tty);
1212                                         continue;
1213                                   case '7':
1214                                         save_cur(currcons);
1215                                         continue;
1216                                   case '8':
1217                                         restore_cur(currcons);
1218                                         continue;
1219                                   case '(':
1220                                         vc_state = ESsetG0;
1221                                         continue;
1222                                   case ')':
1223                                         vc_state = ESsetG1;
1224                                         continue;
1225                                   case '#':
1226                                         vc_state = EShash;
1227                                         continue;
1228                                   case 'c':
1229                                         reset_terminal(currcons,1);
1230                                         continue;
1231                                   case '>':  /* Numeric keypad */
1232                                         clr_kbd(kbdapplic);
1233                                         continue;
1234                                   case '=':  /* Appl. keypad */
1235                                         set_kbd(kbdapplic);
1236                                         continue;
1237                                 }       
1238                                 continue;
1239                         case ESsquare:
1240                                 for(npar = 0 ; npar < NPAR ; npar++)
1241                                         par[npar] = 0;
1242                                 npar = 0;
1243                                 vc_state = ESgetpars;
1244                                 if (c == '[') { /* Function key */
1245                                         vc_state=ESfunckey;
1246                                         continue;
1247                                 }
1248                                 ques = (c=='?');
1249                                 if (ques)
1250                                         continue;
1251                         case ESgetpars:
1252                                 if (c==';' && npar<NPAR-1) {
1253                                         npar++;
1254                                         continue;
1255                                 } else if (c>='0' && c<='9') {
1256                                         par[npar] *= 10;
1257                                         par[npar] += c-'0';
1258                                         continue;
1259                                 } else vc_state=ESgotpars;
1260                         case ESgotpars:
1261                                 vc_state = ESnormal;
1262                                 switch(c) {
1263                                         case 'h':
1264                                                 set_mode(currcons,1);
1265                                                 continue;
1266                                         case 'l':
1267                                                 set_mode(currcons,0);
1268                                                 continue;
1269                                         case 'n':
1270                                                 if (!ques)
1271                                                         if (par[0] == 5)
1272                                                                 status_report(currcons,tty);
1273                                                         else if (par[0] == 6)
1274                                                                 cursor_report(currcons,tty);
1275                                                 continue;
1276                                 }
1277                                 if (ques) {
1278                                         ques = 0;
1279                                         continue;
1280                                 }
1281                                 switch(c) {
1282                                         case 'G': case '`':
1283                                                 if (par[0]) par[0]--;
1284                                                 gotoxy(currcons,par[0],y);
1285                                                 continue;
1286                                         case 'A':
1287                                                 if (!par[0]) par[0]++;
1288                                                 gotoxy(currcons,x,y-par[0]);
1289                                                 continue;
1290                                         case 'B': case 'e':
1291                                                 if (!par[0]) par[0]++;
1292                                                 gotoxy(currcons,x,y+par[0]);
1293                                                 continue;
1294                                         case 'C': case 'a':
1295                                                 if (!par[0]) par[0]++;
1296                                                 gotoxy(currcons,x+par[0],y);
1297                                                 continue;
1298                                         case 'D':
1299                                                 if (!par[0]) par[0]++;
1300                                                 gotoxy(currcons,x-par[0],y);
1301                                                 continue;
1302                                         case 'E':
1303                                                 if (!par[0]) par[0]++;
1304                                                 gotoxy(currcons,0,y+par[0]);
1305                                                 continue;
1306                                         case 'F':
1307                                                 if (!par[0]) par[0]++;
1308                                                 gotoxy(currcons,0,y-par[0]);
1309                                                 continue;
1310                                         case 'd':
1311                                                 if (par[0]) par[0]--;
1312                                                 gotoxy(currcons,x,par[0]);
1313                                                 continue;
1314                                         case 'H': case 'f':
1315                                                 if (par[0]) par[0]--;
1316                                                 if (par[1]) par[1]--;
1317                                                 gotoxy(currcons,par[1],par[0]);
1318                                                 continue;
1319                                         case 'J':
1320                                                 csi_J(currcons,par[0]);
1321                                                 continue;
1322                                         case 'K':
1323                                                 csi_K(currcons,par[0]);
1324                                                 continue;
1325                                         case 'L':
1326                                                 csi_L(currcons,par[0]);
1327                                                 continue;
1328                                         case 'M':
1329                                                 csi_M(currcons,par[0]);
1330                                                 continue;
1331                                         case 'P':
1332                                                 csi_P(currcons,par[0]);
1333                                                 continue;
1334                                         case 'c':
1335                                                 if (!par[0])
1336                                                         respond_ID(currcons,tty);
1337                                                 continue;
1338                                         case 'g':
1339                                                 if (!par[0])
1340                                                         tab_stop[x >> 5] &= ~(1 << (x & 31));
1341                                                 else if (par[0] == 3) {
1342                                                         tab_stop[0] =
1343                                                         tab_stop[1] =
1344                                                         tab_stop[2] =
1345                                                         tab_stop[3] =
1346                                                         tab_stop[4] = 0;
1347                                                 }
1348                                                 continue;
1349                                         case 'm':
1350                                                 csi_m(currcons);
1351                                                 continue;
1352                                         case 'r':
1353                                                 if (!par[0])
1354                                                         par[0]++;
1355                                                 if (!par[1])
1356                                                         par[1] = video_num_lines;
1357                                                 /* Minimum allowed region is 2 lines */
1358                                                 if (par[0] < par[1] &&
1359                                                     par[1] <= video_num_lines) {
1360                                                         top=par[0]-1;
1361                                                         bottom=par[1];
1362                                                         gotoxy(currcons,0,0);
1363                                                 }
1364                                                 continue;
1365                                         case 's':
1366                                                 save_cur(currcons);
1367                                                 continue;
1368                                         case 'u':
1369                                                 restore_cur(currcons);
1370                                                 continue;
1371                                         case 'X':
1372                                                 csi_X(currcons, par[0]);
1373                                                 continue;
1374                                         case '@':
1375                                                 csi_at(currcons,par[0]);
1376                                                 continue;
1377                                         case ']': /* setterm functions */
1378                                                 setterm_command(currcons);
1379                                                 continue;
1380                                 }
1381                                 continue;
1382                         case ESfunckey:
1383                                 vc_state = ESnormal;
1384                                 continue;
1385                         case EShash:
1386                                 vc_state = ESnormal;
1387                                 if (c == '8') {
1388                                         /* DEC screen alignment test. kludge :-) */
1389                                         video_erase_char =
1390                                                 (video_erase_char & 0xff00) | 'E';
1391                                         csi_J(currcons, 2);
1392                                         video_erase_char =
1393                                                 (video_erase_char & 0xff00) | ' ';
1394                                 }
1395                                 continue;
1396                         case ESsetG0:
1397                                 if (c == '0')
1398                                         G0_charset = GRAF_TRANS;
1399                                 else if (c == 'B')
1400                                         G0_charset = NORM_TRANS;
1401                                 else if (c == 'U')
1402                                         G0_charset = NULL_TRANS;
1403                                 else if (c == 'K')
1404                                         G0_charset = USER_TRANS;
1405                                 if (charset == 0)
1406                                         translate = G0_charset;
1407                                 vc_state = ESnormal;
1408                                 continue;
1409                         case ESsetG1:
1410                                 if (c == '0')
1411                                         G1_charset = GRAF_TRANS;
1412                                 else if (c == 'B')
1413                                         G1_charset = NORM_TRANS;
1414                                 else if (c == 'U')
1415                                         G1_charset = NULL_TRANS;
1416                                 else if (c == 'K')
1417                                         G1_charset = USER_TRANS;
1418                                 if (charset == 1)
1419                                         translate = G1_charset;
1420                                 vc_state = ESnormal;
1421                                 continue;
1422                         default:
1423                                 vc_state = ESnormal;
1424                 }
1425         }
1426         if (vcmode != KD_GRAPHICS)
1427                 set_cursor(currcons);
1428         enable_bh(KEYBOARD_BH);
1429         return n;
1430 }
1431 
1432 static int con_write_room(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
1433 {
1434         if (tty->stopped)
1435                 return 0;
1436         return 4096;            /* No limit, really; we're not buffering */
1437 }
1438 
1439 static int con_chars_in_buffer(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
1440 {
1441         return 0;               /* we're not buffering */
1442 }
1443 
1444 void poke_blanked_console(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1445 {
1446         timer_active &= ~(1<<BLANK_TIMER);
1447         if (vt_cons[fg_console].vc_mode == KD_GRAPHICS)
1448                 return;
1449         if (console_blanked) {
1450                 timer_table[BLANK_TIMER].expires = 0;
1451                 timer_active |= 1<<BLANK_TIMER;
1452         } else if (blankinterval) {
1453                 timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
1454                 timer_active |= 1<<BLANK_TIMER;
1455         }
1456 }
1457 
1458 void * memsetw(void * s,unsigned short c,int count)
     /* [previous][next][first][last][top][bottom][index][help] */
1459 {
1460 __asm__("cld\n\t"
1461         "rep\n\t"
1462         "stosw"
1463         : /* no output */
1464         :"a" (c),"D" (s),"c" (count)
1465         :"cx","di");
1466 return s;
1467 }
1468 
1469 void console_print(const char * b)
     /* [previous][next][first][last][top][bottom][index][help] */
1470 {
1471         int currcons = fg_console;
1472         unsigned char c;
1473 
1474         if (!printable || currcons<0 || currcons>=NR_CONSOLES)
1475                 return;
1476         while ((c = *(b++)) != 0) {
1477                 if (c == 10 || c == 13 || need_wrap) {
1478                         if (c != 13)
1479                                 lf(currcons);
1480                         cr(currcons);
1481                         if (c == 10 || c == 13)
1482                                 continue;
1483                 }
1484                 *(unsigned short *) pos = (attr << 8) + c;
1485                 if (x == video_num_columns - 1) {
1486                         need_wrap = 1;
1487                         continue;
1488                 }
1489                 x++;
1490                 pos+=2;
1491         }
1492         set_cursor(currcons);
1493         if (vt_cons[fg_console].vc_mode == KD_GRAPHICS)
1494                 return;
1495         timer_active &= ~(1<<BLANK_TIMER);
1496         if (console_blanked) {
1497                 timer_table[BLANK_TIMER].expires = 0;
1498                 timer_active |= 1<<BLANK_TIMER;
1499         } else if (blankinterval) {
1500                 timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
1501                 timer_active |= 1<<BLANK_TIMER;
1502         }
1503 }
1504 
1505 /*
1506  * con_throttle and con_unthrottle are only used for
1507  * paste_selection(), which has to stuff in a large number of
1508  * characters...
1509  */
1510 static void con_throttle(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
1511 {
1512 }
1513 
1514 static void con_unthrottle(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
1515 {
1516         struct vt_struct *vt = (struct vt_struct *) tty->driver_data;
1517 
1518         wake_up_interruptible(&vt->paste_wait);
1519 }
1520 
1521 /*
1522  *  long con_init(long);
1523  *
1524  * This routine initalizes console interrupts, and does nothing
1525  * else. If you want the screen to clear, call tty_write with
1526  * the appropriate escape-sequece.
1527  *
1528  * Reads the information preserved by setup.s to determine the current display
1529  * type and sets everything accordingly.
1530  */
1531 long con_init(long kmem_start)
     /* [previous][next][first][last][top][bottom][index][help] */
1532 {
1533         char *display_desc = "????";
1534         int currcons = 0;
1535         long base;
1536         int orig_x = ORIG_X;
1537         int orig_y = ORIG_Y;
1538 
1539         memset(&console_driver, 0, sizeof(struct tty_driver));
1540         console_driver.magic = TTY_DRIVER_MAGIC;
1541         console_driver.name = "tty";
1542         console_driver.name_base = 1;
1543         console_driver.major = TTY_MAJOR;
1544         console_driver.minor_start = 1;
1545         console_driver.num = NR_CONSOLES;
1546         console_driver.type = TTY_DRIVER_TYPE_CONSOLE;
1547         console_driver.init_termios = tty_std_termios;
1548         console_driver.flags = TTY_DRIVER_REAL_RAW;
1549         console_driver.refcount = &console_refcount;
1550         console_driver.table = console_table;
1551         console_driver.termios = console_termios;
1552         console_driver.termios_locked = console_termios_locked;
1553 
1554         console_driver.open = con_open;
1555         console_driver.write = con_write;
1556         console_driver.write_room = con_write_room;
1557         console_driver.chars_in_buffer = con_chars_in_buffer;
1558         console_driver.ioctl = vt_ioctl;
1559         console_driver.stop = con_stop;
1560         console_driver.start = con_start;
1561         console_driver.throttle = con_throttle;
1562         console_driver.unthrottle = con_unthrottle;
1563         
1564         if (tty_register_driver(&console_driver))
1565                 panic("Couldn't register console driver\n");
1566         
1567         vc_scrmembuf = (unsigned short *) kmem_start;
1568         video_num_columns = ORIG_VIDEO_COLS;
1569         video_size_row = video_num_columns * 2;
1570         video_num_lines = ORIG_VIDEO_LINES;
1571         video_page = ORIG_VIDEO_PAGE;
1572         screen_size = (video_num_lines * video_size_row);
1573         kmem_start += NR_CONSOLES * screen_size;
1574         timer_table[BLANK_TIMER].fn = blank_screen;
1575         timer_table[BLANK_TIMER].expires = 0;
1576         if (blankinterval) {
1577                 timer_table[BLANK_TIMER].expires = jiffies+blankinterval;
1578                 timer_active |= 1<<BLANK_TIMER;
1579         }
1580         
1581         if (ORIG_VIDEO_MODE == 7)       /* Is this a monochrome display? */
1582         {
1583                 video_mem_base = 0xb0000;
1584                 video_port_reg = 0x3b4;
1585                 video_port_val = 0x3b5;
1586                 if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
1587                 {
1588                         video_type = VIDEO_TYPE_EGAM;
1589                         video_mem_term = 0xb8000;
1590                         display_desc = "EGA+";
1591                 }
1592                 else
1593                 {
1594                         video_type = VIDEO_TYPE_MDA;
1595                         video_mem_term = 0xb2000;
1596                         display_desc = "*MDA";
1597                 }
1598         }
1599         else                            /* If not, it is color. */
1600         {
1601                 can_do_color = 1;
1602                 video_mem_base = 0xb8000;
1603                 video_port_reg  = 0x3d4;
1604                 video_port_val  = 0x3d5;
1605                 if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
1606                 {
1607                         video_type = VIDEO_TYPE_EGAC;
1608                         video_mem_term = 0xc0000;
1609                         display_desc = "EGA+";
1610                 }
1611                 else
1612                 {
1613                         video_type = VIDEO_TYPE_CGA;
1614                         video_mem_term = 0xba000;
1615                         display_desc = "*CGA";
1616                 }
1617         }
1618         
1619         /* Initialize the variables used for scrolling (mostly EGA/VGA) */
1620 
1621         base = (long)vc_scrmembuf;
1622         for (currcons = 0; currcons<NR_CONSOLES; currcons++) {
1623                 pos = origin = video_mem_start = base;
1624                 scr_end = video_mem_end = (base += screen_size);
1625                 vc_scrbuf[currcons] = (unsigned short *) origin;
1626                 vcmode          = KD_TEXT;
1627                 vtmode.mode     = VT_AUTO;
1628                 vtmode.waitv    = 0;
1629                 vtmode.relsig   = 0;
1630                 vtmode.acqsig   = 0;
1631                 vtmode.frsig    = 0;
1632                 vtpid           = -1;
1633                 vtnewvt         = -1;
1634                 clr_kbd(kbdraw);
1635                 def_color       = 0x07;   /* white */
1636                 ulcolor         = 0x0f;   /* bold white */
1637                 halfcolor       = 0x08;   /* grey */
1638                 vt_cons[currcons].paste_wait = 0;
1639                 reset_terminal(currcons, currcons);
1640         }
1641         currcons = fg_console = 0;
1642 
1643         video_mem_start = video_mem_base;
1644         video_mem_end = video_mem_term;
1645         origin = video_mem_start;
1646         scr_end = video_mem_start + video_num_lines * video_size_row;
1647         gotoxy(currcons,0,0);
1648         save_cur(currcons);
1649         gotoxy(currcons,orig_x,orig_y);
1650         update_screen(fg_console);
1651         printable = 1;
1652         printk("Console: %s %s %ldx%ld, %d virtual consoles\n",
1653                 can_do_color?"colour":"mono",
1654                 display_desc,
1655                 video_num_columns,video_num_lines,
1656                 NR_CONSOLES);
1657         register_console(console_print);
1658         return kmem_start;
1659 }
1660 
1661 /*
1662  * kbdsave doesn't need to do anything: it's all handled automatically
1663  * with the new data structures..
1664  */
1665 void kbdsave(int new_console)
     /* [previous][next][first][last][top][bottom][index][help] */
1666 {
1667 }
1668 
1669 static void get_scrmem(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
1670 {
1671         memcpy((void *)vc_scrbuf[currcons],(void *)origin, screen_size);
1672         video_mem_start = (unsigned long)vc_scrbuf[currcons];
1673         origin  = video_mem_start;
1674         scr_end = video_mem_end = video_mem_start+screen_size;
1675         pos = origin + y*video_size_row + (x<<1);
1676 }
1677 
1678 static void set_scrmem(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
1679 {
1680 #ifdef CONFIG_HGA
1681   /* This works with XFree86 1.2, 1.3 and 2.0
1682      This code could be extended and made more generally useful if we could
1683      determine the actual video mode. It appears that this should be
1684      possible on a genuine Hercules card, but I (WM) haven't been able to
1685      read from any of the required registers on my clone card.
1686      */
1687         /* This code should work with Hercules and MDA cards. */
1688         if (video_type == VIDEO_TYPE_MDA)
1689           {
1690             if (vcmode == KD_TEXT)
1691               {
1692                 /* Ensure that the card is in text mode. */
1693                 int     i;
1694                 static char herc_txt_tbl[12] = {
1695                   0x61,0x50,0x52,0x0f,0x19,6,0x19,0x19,2,0x0d,0x0b,0x0c };
1696                 outb_p(0, 0x3bf);  /* Back to power-on defaults */
1697                 outb_p(0, 0x3b8);  /* Blank the screen, select page 0, etc */
1698                 for ( i = 0 ; i < 12 ; i++ )
1699                   {
1700                     outb_p(i, 0x3b4);
1701                     outb_p(herc_txt_tbl[i], 0x3b5);
1702                   }
1703               }
1704 #define HGA_BLINKER_ON 0x20
1705 #define HGA_SCREEN_ON  8
1706             /* Make sure that the hardware is not blanked */
1707             outb_p(HGA_BLINKER_ON | HGA_SCREEN_ON, 0x3b8);
1708           }
1709 #endif CONFIG_HGA
1710 
1711         video_mem_start = video_mem_base;
1712         video_mem_end = video_mem_term;
1713         origin  = video_mem_start;
1714         scr_end = video_mem_start + screen_size;
1715         pos = origin + y*video_size_row + (x<<1);
1716         memcpy((void *)video_mem_base, (void *)vc_scrbuf[fg_console], screen_size);
1717 }
1718 
1719 void blank_screen(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1720 {
1721         if (console_blanked)
1722                 return;
1723         timer_table[BLANK_TIMER].fn = unblank_screen;
1724         get_scrmem(fg_console);
1725         hide_cursor();
1726         console_blanked = 1;
1727         memsetw((void *)video_mem_base, 0x0020, video_mem_term-video_mem_base );
1728 }
1729 
1730 void unblank_screen(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1731 {
1732         if (!console_blanked)
1733                 return;
1734         timer_table[BLANK_TIMER].fn = blank_screen;
1735         if (blankinterval) {
1736                 timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
1737                 timer_active |= 1<<BLANK_TIMER;
1738         }
1739         console_blanked = 0;
1740         set_scrmem(fg_console);
1741         set_origin(fg_console);
1742         set_cursor(fg_console);
1743 }
1744 
1745 void update_screen(int new_console)
     /* [previous][next][first][last][top][bottom][index][help] */
1746 {
1747         static int lock = 0;
1748 
1749         if (new_console == fg_console || lock)
1750                 return;
1751         lock = 1;
1752         kbdsave(new_console);
1753 #ifdef CONFIG_SELECTION
1754         highlight_pointer(fg_console,-1);
1755 #endif /* CONFIG_SELECTION */
1756         get_scrmem(fg_console); 
1757         fg_console = new_console;
1758         set_scrmem(fg_console); 
1759         set_origin(fg_console);
1760         set_cursor(new_console);
1761         set_leds();
1762         compute_shiftstate();
1763         lock = 0;
1764 }
1765 
1766 int do_screendump(int arg)
     /* [previous][next][first][last][top][bottom][index][help] */
1767 {
1768         char *sptr, *buf = (char *)arg;
1769         int currcons, l;
1770 
1771         if (!suser())
1772                 return -EPERM;
1773         l = verify_area(VERIFY_WRITE, buf,2+video_num_columns*video_num_lines);
1774         if (l)
1775                 return l;
1776         currcons = get_fs_byte(buf+1);
1777         if ((currcons<0) || (currcons>NR_CONSOLES))
1778                 return -EIO;
1779         put_fs_byte((char)(video_num_lines),buf++);     
1780         put_fs_byte((char)(video_num_columns),buf++);
1781         currcons = (currcons ? currcons-1 : fg_console);
1782         sptr = (char *) origin;
1783         for (l=video_num_lines*video_num_columns; l>0 ; l--, sptr++)
1784                 put_fs_byte(*sptr++,buf++);     
1785         return(0);
1786 }
1787 
1788 /*
1789  * Later on maybe we'll dynamically allocate the console screen
1790  * memory.
1791  */
1792 int con_open(struct tty_struct *tty, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
1793 {
1794         int     idx;
1795 
1796         idx = MINOR(tty->device) - tty->driver.minor_start;
1797         
1798         if (idx > NR_CONSOLES)
1799                 return -ENODEV;
1800         vt_cons[idx].vc_num = idx;
1801         tty->driver_data = &vt_cons[idx];
1802         
1803         if (!tty->winsize.ws_row && !tty->winsize.ws_col) {
1804                 tty->winsize.ws_row = video_num_lines;
1805                 tty->winsize.ws_col = video_num_columns;
1806         }
1807         return 0;
1808 }
1809 
1810 #ifdef CONFIG_SELECTION
1811 /* correction factor for when screen is hardware-scrolled */
1812 #define hwscroll_offset (currcons == fg_console ? ((__real_origin - __origin) << 1) : 0)
1813 
1814 /* set reverse video on characters s-e of console with selection. */
1815 static void highlight(const int currcons, const int s, const int e)
     /* [previous][next][first][last][top][bottom][index][help] */
1816 {
1817         unsigned char *p, *p1, *p2;
1818 
1819         p1 = (unsigned char *)origin - hwscroll_offset + s + 1;
1820         p2 = (unsigned char *)origin - hwscroll_offset + e + 1;
1821         if (p1 > p2)
1822         {
1823                 p = p1;
1824                 p1 = p2;
1825                 p2 = p;
1826         }
1827         for (p = p1; p <= p2; p += 2)
1828                 *p = (*p & 0x88) | ((*p << 4) & 0x70) | ((*p >> 4) & 0x07);
1829 }
1830 
1831 /* use complementary color to show the pointer */
1832 static void highlight_pointer(const int currcons, const int where)
     /* [previous][next][first][last][top][bottom][index][help] */
1833 {
1834         unsigned char *p;
1835         static char *prev=NULL;
1836 
1837         if (where==-1) /* remove the pointer */
1838         {
1839                 if (prev)
1840                 {
1841                         *prev ^= 0x77;
1842                         prev=NULL;
1843                 }
1844         }
1845         else
1846         {
1847                 p = (unsigned char *)origin - hwscroll_offset + where + 1;
1848                 *p ^= 0x77;
1849                 if (prev) *prev ^= 0x77; /* remove the previous one */
1850                 prev=p;
1851         }
1852 }
1853 
1854 
1855 /*
1856  * This function uses a 128-bit look up table
1857  */
1858 static unsigned long inwordLut[4]={
1859   0x00000000, /* control chars     */
1860   0x03FF0000, /* digits            */
1861   0x87FFFFFE, /* uppercase and '_' */
1862   0x07FFFFFE  /* lowercase         */
1863 };
1864 static inline int inword(const char c) {
     /* [previous][next][first][last][top][bottom][index][help] */
1865    return ( inwordLut[(c>>5)&3] >> (c&0x1F) ) & 1;
1866 }
1867 
1868 /* set inwordLut conntents. Invoked by ioctl(). */
1869 int sel_loadlut(const int arg)
     /* [previous][next][first][last][top][bottom][index][help] */
1870 {
1871     memcpy_fromfs(inwordLut,(unsigned long *)(arg+4),16);
1872     return 0;
1873 }
1874 
1875 /* does screen address p correspond to character at LH/RH edge of screen? */
1876 static inline int atedge(const int p)
     /* [previous][next][first][last][top][bottom][index][help] */
1877 {
1878         return (!(p % video_size_row) || !((p + 2) % video_size_row));
1879 }
1880 
1881 /* constrain v such that l <= v <= u */
1882 static inline short limit(const int v, const int l, const int u)
     /* [previous][next][first][last][top][bottom][index][help] */
1883 {
1884         return (v < l) ? l : ((v > u) ? u : v);
1885 }
1886 
1887 /* invoked via ioctl(TIOCLINUX) */
1888 int mouse_reporting(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1889 {
1890         int currcons = fg_console;
1891 
1892         return report_mouse;
1893 }
1894 
1895 /* set the current selection. Invoked by ioctl(). */
1896 int set_selection(const int arg, struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
1897 {
1898         unsigned short *args, xs, ys, xe, ye;
1899         int currcons = fg_console;
1900         int sel_mode, new_sel_start, new_sel_end, spc;
1901         char *bp, *obp, *spos;
1902         int i, ps, pe;
1903         char *off = (char *)origin - hwscroll_offset;
1904 
1905         unblank_screen();
1906         args = (unsigned short *)(arg + 1);
1907         xs = get_fs_word(args++) - 1;
1908         ys = get_fs_word(args++) - 1;
1909         xe = get_fs_word(args++) - 1;
1910         ye = get_fs_word(args++) - 1;
1911         sel_mode = get_fs_word(args);
1912 
1913         xs = limit(xs, 0, video_num_columns - 1);
1914         ys = limit(ys, 0, video_num_lines - 1);
1915         xe = limit(xe, 0, video_num_columns - 1);
1916         ye = limit(ye, 0, video_num_lines - 1);
1917         ps = ys * video_size_row + (xs << 1);
1918         pe = ye * video_size_row + (xe << 1);
1919 
1920         if (report_mouse && (sel_mode & 16)) {
1921                 mouse_report(currcons, tty, sel_mode & 15, xs, ys);
1922                 return 0;
1923         }
1924 
1925         if (ps > pe)    /* make sel_start <= sel_end */
1926         {
1927                 int tmp = ps;
1928                 ps = pe;
1929                 pe = tmp;
1930         }
1931 
1932         switch (sel_mode)
1933         {
1934                 case 0: /* character-by-character selection */
1935                         new_sel_start = ps;
1936                         new_sel_end = pe;
1937                         break;
1938                 case 1: /* word-by-word selection */
1939                         spc = isspace(*(off + ps));
1940                         for (new_sel_start = ps; ; ps -= 2)
1941                         {
1942                                 if ((spc && !isspace(*(off + ps))) ||
1943                                     (!spc && !inword(*(off + ps))))
1944                                         break;
1945                                 new_sel_start = ps;
1946                                 if (!(ps % video_size_row))
1947                                         break;
1948                         }
1949                         spc = isspace(*(off + pe));
1950                         for (new_sel_end = pe; ; pe += 2)
1951                         {
1952                                 if ((spc && !isspace(*(off + pe))) ||
1953                                     (!spc && !inword(*(off + pe))))
1954                                         break;
1955                                 new_sel_end = pe;
1956                                 if (!((pe + 2) % video_size_row))
1957                                         break;
1958                         }
1959                         break;
1960                 case 2: /* line-by-line selection */
1961                         new_sel_start = ps - ps % video_size_row;
1962                         new_sel_end = pe + video_size_row
1963                                     - pe % video_size_row - 2;
1964                         break;
1965                 case 3: /* pointer highlight */
1966                         if (sel_cons != currcons)
1967                         {
1968                                 highlight_pointer(sel_cons,-1);
1969                                 clear_selection();
1970                                 sel_cons = currcons;
1971                         }
1972                         highlight_pointer(sel_cons,pe);
1973                         return 0; /* nothing more */
1974                 default:
1975                         return -EINVAL;
1976         }
1977         /* select to end of line if on trailing space */
1978         if (new_sel_end > new_sel_start &&
1979                 !atedge(new_sel_end) && isspace(*(off + new_sel_end)))
1980         {
1981                 for (pe = new_sel_end + 2; ; pe += 2)
1982                 {
1983                         if (!isspace(*(off + pe)) || atedge(pe))
1984                                 break;
1985                 }
1986                 if (isspace(*(off + pe)))
1987                         new_sel_end = pe;
1988         }
1989         if (sel_cons != currcons)
1990         {
1991                 clear_selection();
1992                 sel_cons = currcons;
1993         }
1994         if (sel_start == -1)    /* no current selection */
1995                 highlight(sel_cons, new_sel_start, new_sel_end);
1996         else if (new_sel_start == sel_start)
1997         {
1998                 if (new_sel_end == sel_end)     /* no action required */
1999                         return 0;
2000                 else if (new_sel_end > sel_end) /* extend to right */
2001                         highlight(sel_cons, sel_end + 2, new_sel_end);
2002                 else                            /* contract from right */
2003                         highlight(sel_cons, new_sel_end + 2, sel_end);
2004         }
2005         else if (new_sel_end == sel_end)
2006         {
2007                 if (new_sel_start < sel_start)  /* extend to left */
2008                         highlight(sel_cons, new_sel_start, sel_start - 2);
2009                 else                            /* contract from left */
2010                         highlight(sel_cons, sel_start, new_sel_start - 2);
2011         }
2012         else    /* some other case; start selection from scratch */
2013         {
2014                 clear_selection();
2015                 highlight(sel_cons, new_sel_start, new_sel_end);
2016         }
2017         sel_start = new_sel_start;
2018         sel_end = new_sel_end;
2019         obp = bp = sel_buffer;
2020         for (i = sel_start; i <= sel_end; i += 2)
2021         {
2022                 spos = (char *)off + i;
2023                 *bp++ = *spos;
2024                 if (!isspace(*spos))
2025                         obp = bp;
2026                 if (! ((i + 2) % video_size_row))
2027                 {
2028                         /* strip trailing blanks from line and add newline,
2029                            unless non-space at end of line. */
2030                         if (obp != bp)
2031                         {
2032                                 bp = obp;
2033                                 *bp++ = '\r';
2034                         }
2035                         obp = bp;
2036                 }
2037                 /* check for space, leaving room for next character, possible
2038                    newline, and null at end. */
2039                 if (bp - sel_buffer > SEL_BUFFER_SIZE - 3)
2040                         break;
2041         }
2042         *bp = '\0';
2043         return 0;
2044 }
2045 
2046 /* insert the contents of the selection buffer into the queue of the
2047    tty associated with the current console. Invoked by ioctl(). */
2048 int paste_selection(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
2049 {
2050         struct wait_queue wait = { current, NULL };
2051         char    *bp = sel_buffer;
2052         int     c, l;
2053         struct vt_struct *vt = (struct vt_struct *) tty->driver_data;
2054         
2055         if (!sel_buffer[0])
2056                 return 0;
2057         unblank_screen();
2058         c = strlen(sel_buffer);
2059         current->state = TASK_INTERRUPTIBLE;
2060         add_wait_queue(&vt->paste_wait, &wait);
2061         while (c) {
2062                 if (test_bit(TTY_THROTTLED, &tty->flags)) {
2063                         schedule();
2064                         continue;
2065                 }
2066                 l = MIN(c, tty->ldisc.receive_room(tty));
2067                 tty->ldisc.receive_buf(tty, bp, 0, l);
2068                 c -= l;
2069                 bp += l;
2070         }
2071         current->state = TASK_RUNNING;
2072         return 0;
2073 }
2074 
2075 /* remove the current selection highlight, if any, from the console holding
2076    the selection. */
2077 static void clear_selection()
     /* [previous][next][first][last][top][bottom][index][help] */
2078 {
2079         highlight_pointer(sel_cons, -1); /* hide the pointer */
2080         if (sel_start != -1)
2081         {
2082                 highlight(sel_cons, sel_start, sel_end);
2083                 sel_start = -1;
2084         }
2085 }
2086 #endif /* CONFIG_SELECTION */
2087 
2088 /*
2089  * PIO_FONT support.
2090  *
2091  * The font loading code goes back to the codepage package by
2092  * Joel Hoffman (joel@wam.umd.edu). (He reports that the original
2093  * reference is: "From: p. 307 of _Programmer's Guide to PC & PS/2
2094  * Video Systems_ by Richard Wilton. 1987.  Microsoft Press".)
2095  *
2096  * Change for certain monochrome monitors by Yury Shevchuck
2097  * (sizif@botik.yaroslavl.su).
2098  */
2099 
2100 #define colourmap ((char *)0xa0000)
2101 #define blackwmap ((char *)0xb0000)
2102 #define cmapsz 8192
2103 #define seq_port_reg (0x3c4)
2104 #define seq_port_val (0x3c5)
2105 #define gr_port_reg (0x3ce)
2106 #define gr_port_val (0x3cf)
2107 
2108 static int set_get_font(char * arg, int set)
     /* [previous][next][first][last][top][bottom][index][help] */
2109 {
2110 #ifdef CAN_LOAD_EGA_FONTS
2111         int i;
2112         char *charmap;
2113         int beg;
2114 
2115         /* no use to "load" CGA... */
2116 
2117         if (video_type == VIDEO_TYPE_EGAC) {
2118                 charmap = colourmap;
2119                 beg = 0x0e;
2120         } else if (video_type == VIDEO_TYPE_EGAM) {
2121                 charmap = blackwmap;
2122                 beg = 0x0a;
2123         } else
2124                 return -EINVAL;
2125 
2126         i = verify_area(set ? VERIFY_READ : VERIFY_WRITE, (void *)arg, cmapsz);
2127         if (i)
2128                 return i;
2129 
2130         cli();
2131         outb_p( 0x00, seq_port_reg );   /* First, the sequencer */
2132         outb_p( 0x01, seq_port_val );   /* Synchronous reset */
2133         outb_p( 0x02, seq_port_reg );
2134         outb_p( 0x04, seq_port_val );   /* CPU writes only to map 2 */
2135         outb_p( 0x04, seq_port_reg );
2136         outb_p( 0x07, seq_port_val );   /* Sequential addressing */
2137         outb_p( 0x00, seq_port_reg );
2138         outb_p( 0x03, seq_port_val );   /* Clear synchronous reset */
2139 
2140         outb_p( 0x04, gr_port_reg );    /* Now, the graphics controller */
2141         outb_p( 0x02, gr_port_val );    /* select map 2 */
2142         outb_p( 0x05, gr_port_reg );
2143         outb_p( 0x00, gr_port_val );    /* disable odd-even addressing */
2144         outb_p( 0x06, gr_port_reg );
2145         outb_p( 0x00, gr_port_val );    /* map start at A000:0000 */
2146         sti();
2147 
2148         if (set)
2149                 for (i=0; i<cmapsz ; i++)
2150                         *(charmap+i) = get_fs_byte(arg+i);
2151         else
2152                 for (i=0; i<cmapsz ; i++)
2153                         put_fs_byte(*(charmap+i), arg+i);
2154 
2155         cli();
2156         outb_p( 0x00, seq_port_reg );   /* Frist, the sequencer */
2157         outb_p( 0x01, seq_port_val );   /* Synchronous reset */
2158         outb_p( 0x02, seq_port_reg );
2159         outb_p( 0x03, seq_port_val );   /* CPU writes to maps 0 and 1 */
2160         outb_p( 0x04, seq_port_reg );
2161         outb_p( 0x03, seq_port_val );   /* odd-even addressing */
2162         outb_p( 0x00, seq_port_reg );
2163         outb_p( 0x03, seq_port_val );   /* clear synchronous reset */
2164 
2165         outb_p( 0x04, gr_port_reg );    /* Now, the graphics controller */
2166         outb_p( 0x00, gr_port_val );    /* select map 0 for CPU */
2167         outb_p( 0x05, gr_port_reg );
2168         outb_p( 0x10, gr_port_val );    /* enable even-odd addressing */
2169         outb_p( 0x06, gr_port_reg );
2170         outb_p( beg, gr_port_val );     /* map starts at b800:0 or b000:0 */
2171         sti();
2172 
2173         return 0;
2174 #else
2175         return -EINVAL;
2176 #endif
2177 }
2178 
2179 /*
2180  * Load font into the EGA/VGA character generator. arg points to a 8192
2181  * byte map, 32 bytes per character. Only first H of them are used for
2182  * 8xH fonts (0 < H <= 32).
2183  */
2184 
2185 int con_set_font (char *arg)
     /* [previous][next][first][last][top][bottom][index][help] */
2186 {
2187         return set_get_font (arg,1);
2188 }
2189 
2190 int con_get_font (char *arg)
     /* [previous][next][first][last][top][bottom][index][help] */
2191 {
2192         return set_get_font (arg,0);
2193 }
2194 
2195 /*
2196  * Load customizable translation table (USER_TRANS[]). All checks are here,
2197  * so we need only include 'return con_set_trans(arg)' in the ioctl handler
2198  * arg points to a 256 byte translation table.
2199  */
2200 int con_set_trans(char * arg)
     /* [previous][next][first][last][top][bottom][index][help] */
2201 {
2202         int i;
2203 
2204         i = verify_area(VERIFY_READ, (void *)arg, E_TABSZ);
2205         if (i)
2206                 return i;
2207 
2208         for (i=0; i<E_TABSZ ; i++) USER_TRANS[i] = get_fs_byte(arg+i);
2209         USER_TRANS[012]=0;
2210         USER_TRANS[014]=0;
2211         USER_TRANS[015]=0;
2212         USER_TRANS[033]=0;
2213         return 0;
2214 }
2215 
2216 int con_get_trans(char * arg)
     /* [previous][next][first][last][top][bottom][index][help] */
2217 {
2218         int i;
2219 
2220         i = verify_area(VERIFY_WRITE, (void *)arg, E_TABSZ);
2221         if (i)
2222                 return i;
2223 
2224         for (i=0; i<E_TABSZ ; i++) put_fs_byte(USER_TRANS[i],arg+i);
2225         return 0;
2226 }

/* [previous][next][first][last][top][bottom][index][help] */