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 #ifdef CONFIG_SELECTION
 805 static void mouse_report(int currcons, struct tty_struct * tty,
     /* [previous][next][first][last][top][bottom][index][help] */
 806                          int butt, int mrx, int mry)
 807 {
 808         char buf[8];
 809 
 810         sprintf(buf, "\033[M%c%c%c", (char)(' ' + butt), (char)('!' + mrx),
 811                 (char)('!' + mry));
 812         respond_string(buf, tty);
 813 }
 814 #endif
 815 
 816 static inline void status_report(int currcons, struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 817 {
 818         respond_string("\033[0n", tty); /* Terminal ok */
 819 }
 820 
 821 static inline void respond_ID(int currcons, struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 822 {
 823         respond_string(VT102ID, tty);
 824 }
 825 
 826 static void invert_screen(int currcons) {
     /* [previous][next][first][last][top][bottom][index][help] */
 827         unsigned char *p;
 828 
 829         if (can_do_color)
 830                 for (p = (unsigned char *)origin+1; p < (unsigned char *)scr_end; p+=2)
 831                         *p = (*p & 0x88) | (((*p >> 4) | (*p << 4)) & 0x77);
 832         else
 833                 for (p = (unsigned char *)origin+1; p < (unsigned char *)scr_end; p+=2)
 834                         *p ^= *p & 0x07 == 1 ? 0x70 : 0x77;
 835 }
 836 
 837 static void set_mode(int currcons, int on_off)
     /* [previous][next][first][last][top][bottom][index][help] */
 838 {
 839         int i;
 840 
 841         for (i=0; i<=npar; i++)
 842                 if (ques) switch(par[i]) {      /* DEC private modes set/reset */
 843                         case 1:                 /* Cursor keys send ^[Ox/^[[x */
 844                                 if (on_off)
 845                                         set_kbd(decckm);
 846                                 else
 847                                         clr_kbd(decckm);
 848                                 break;
 849                         case 3: /* 80/132 mode switch unimplemented */
 850                                 csi_J(currcons,2);
 851                                 gotoxy(currcons,0,0);
 852                                 break;
 853                         case 5:                 /* Inverted screen on/off */
 854                                 if (decscnm != on_off) {
 855                                         decscnm = on_off;
 856                                         invert_screen(currcons);
 857                                         update_attr(currcons);
 858                                 }
 859                                 break;
 860                         case 6:                 /* Origin relative/absolute */
 861                                 decom = on_off;
 862                                 gotoxy(currcons,0,0);
 863                                 break;
 864                         case 7:                 /* Autowrap on/off */
 865                                 decawm = on_off;
 866                                 break;
 867                         case 8:                 /* Autorepeat on/off */
 868                                 if (on_off)
 869                                         set_kbd(decarm);
 870                                 else
 871                                         clr_kbd(decarm);
 872                                 break;
 873                         case 9:
 874                                 report_mouse = on_off ? 1 : 0;
 875                                 break;
 876                         case 25:                /* Cursor on/off */
 877                                 deccm = on_off;
 878                                 set_cursor(currcons);
 879                                 break;
 880                         case 1000:
 881                                 report_mouse = on_off ? 2 : 0;
 882                                 break;
 883                 } else switch(par[i]) {         /* ANSI modes set/reset */
 884                         case 4:                 /* Insert Mode on/off */
 885                                 decim = on_off;
 886                                 break;
 887                         case 20:                /* Lf, Enter == CrLf/Lf */
 888                                 if (on_off)
 889                                         set_kbd(lnm);
 890                                 else
 891                                         clr_kbd(lnm);
 892                                 break;
 893                 }
 894 }
 895 
 896 static void setterm_command(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 897 {
 898         switch(par[0]) {
 899                 case 1: /* set color for underline mode */
 900                         if (can_do_color && par[1] < 16) {
 901                                 ulcolor = color_table[par[1]];
 902                                 if (underline)
 903                                         update_attr(currcons);
 904                         }
 905                         break;
 906                 case 2: /* set color for half intensity mode */
 907                         if (can_do_color && par[1] < 16) {
 908                                 halfcolor = color_table[par[1]];
 909                                 if (intensity == 0)
 910                                         update_attr(currcons);
 911                         }
 912                         break;
 913                 case 8: /* store colors as defaults */
 914                         def_color = attr;
 915                         default_attr(currcons);
 916                         update_attr(currcons);
 917                         break;
 918                 case 9: /* set blanking interval */
 919                         blankinterval = ((par[1] < 60) ? par[1] : 60) * 60 * HZ;
 920                         break;
 921         }
 922 }
 923 
 924 static void insert_char(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 925 {
 926         unsigned int i = x;
 927         unsigned short tmp, old = video_erase_char;
 928         unsigned short * p = (unsigned short *) pos;
 929 
 930         while (i++ < video_num_columns) {
 931                 tmp = *p;
 932                 *p = old;
 933                 old = tmp;
 934                 p++;
 935         }
 936         need_wrap = 0;
 937 }
 938 
 939 static void insert_line(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 940 {
 941         scrdown(currcons,y,bottom);
 942         need_wrap = 0;
 943 }
 944 
 945 static void delete_char(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 946 {
 947         unsigned int i = x;
 948         unsigned short * p = (unsigned short *) pos;
 949 
 950         while (++i < video_num_columns) {
 951                 *p = *(p+1);
 952                 p++;
 953         }
 954         *p = video_erase_char;
 955         need_wrap = 0;
 956 }
 957 
 958 static void delete_line(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 959 {
 960         scrup(currcons,y,bottom);
 961         need_wrap = 0;
 962 }
 963 
 964 static void csi_at(int currcons, unsigned int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
 965 {
 966         if (nr > video_num_columns)
 967                 nr = video_num_columns;
 968         else if (!nr)
 969                 nr = 1;
 970         while (nr--)
 971                 insert_char(currcons);
 972 }
 973 
 974 static void csi_L(int currcons, unsigned int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
 975 {
 976         if (nr > video_num_lines)
 977                 nr = video_num_lines;
 978         else if (!nr)
 979                 nr = 1;
 980         while (nr--)
 981                 insert_line(currcons);
 982 }
 983 
 984 static void csi_P(int currcons, unsigned int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
 985 {
 986         if (nr > video_num_columns)
 987                 nr = video_num_columns;
 988         else if (!nr)
 989                 nr = 1;
 990         while (nr--)
 991                 delete_char(currcons);
 992 }
 993 
 994 static void csi_M(int currcons, unsigned int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
 995 {
 996         if (nr > video_num_lines)
 997                 nr = video_num_lines;
 998         else if (!nr)
 999                 nr=1;
1000         while (nr--)
1001                 delete_line(currcons);
1002 }
1003 
1004 static void save_cur(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
1005 {
1006         saved_x         = x;
1007         saved_y         = y;
1008         s_intensity     = intensity;
1009         s_underline     = underline;
1010         s_blink         = blink;
1011         s_reverse       = reverse;
1012         s_charset       = charset;
1013         s_color         = color;
1014         saved_G0        = G0_charset;
1015         saved_G1        = G1_charset;
1016 }
1017 
1018 static void restore_cur(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
1019 {
1020         gotoxy(currcons,saved_x,saved_y);
1021         intensity       = s_intensity;
1022         underline       = s_underline;
1023         blink           = s_blink;
1024         reverse         = s_reverse;
1025         charset         = s_charset;
1026         color           = s_color;
1027         G0_charset      = saved_G0;
1028         G1_charset      = saved_G1;
1029         translate       = charset ? G1_charset : G0_charset;
1030         update_attr(currcons);
1031         need_wrap = 0;
1032 }
1033 
1034 enum { ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey, 
1035         EShash, ESsetG0, ESsetG1, ESignore };
1036 
1037 static void reset_terminal(int currcons, int do_clear)
     /* [previous][next][first][last][top][bottom][index][help] */
1038 {
1039         top             = 0;
1040         bottom          = video_num_lines;
1041         vc_state                = ESnormal;
1042         ques            = 0;
1043         translate       = NORM_TRANS;
1044         G0_charset      = NORM_TRANS;
1045         G1_charset      = GRAF_TRANS;
1046         charset         = 0;
1047         need_wrap       = 0;
1048         report_mouse    = 0;
1049 
1050         disp_ctrl       = 0;
1051         toggle_meta     = 0;
1052 
1053         decscnm         = 0;
1054         decom           = 0;
1055         decawm          = 1;
1056         deccm           = 1;
1057         decim           = 0;
1058 
1059         set_kbd(decarm);
1060         clr_kbd(decckm);
1061         clr_kbd(kbdapplic);
1062         clr_kbd(lnm);
1063         kbd_table[currcons].lockstate = 0;
1064         kbd_table[currcons].ledstate = kbd_table[currcons].default_ledstate;
1065         set_leds();
1066 
1067         default_attr(currcons);
1068         update_attr(currcons);
1069 
1070         tab_stop[0]     = 0x01010100;
1071         tab_stop[1]     =
1072         tab_stop[2]     =
1073         tab_stop[3]     =
1074         tab_stop[4]     = 0x01010101;
1075 
1076         if (do_clear) {
1077                 gotoxy(currcons,0,0);
1078                 csi_J(currcons,2);
1079                 save_cur(currcons);
1080         }
1081 }
1082 
1083 /*
1084  * Turn the Scroll-Lock LED on when the tty is stopped
1085  */
1086 static void con_stop(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
1087 {
1088         int console_num;
1089         if (!tty)
1090                 return;
1091         console_num = MINOR(tty->device) - (tty->driver.minor_start);
1092         if (console_num < 0 || console_num >= NR_CONSOLES)
1093                 return;
1094         set_vc_kbd_led(kbd_table + console_num, VC_SCROLLOCK);
1095         set_leds();
1096 }
1097 
1098 /*
1099  * Turn the Scroll-Lock LED off when the console is started
1100  */
1101 static void con_start(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
1102 {
1103         int console_num;
1104         if (!tty)
1105                 return;
1106         console_num = MINOR(tty->device) - (tty->driver.minor_start);
1107         if (console_num < 0 || console_num >= NR_CONSOLES)
1108                 return;
1109         clr_vc_kbd_led(kbd_table + console_num, VC_SCROLLOCK);
1110         set_leds();
1111 }
1112 
1113 static int con_write(struct tty_struct * tty, int from_user,
     /* [previous][next][first][last][top][bottom][index][help] */
1114                      unsigned char *buf, int count)
1115 {
1116         int c, n = 0;
1117         unsigned int currcons;
1118         struct vt_struct *vt = (struct vt_struct *)tty->driver_data;
1119 
1120         currcons = vt->vc_num;
1121         if (currcons >= NR_CONSOLES) {
1122                 printk("con_write: illegal vc index (%d)\n", currcons);
1123                 return 0;
1124         }
1125 #ifdef CONFIG_SELECTION
1126         /* clear the selection */
1127         if (currcons == sel_cons)
1128                 clear_selection();
1129 #endif /* CONFIG_SELECTION */
1130         disable_bh(KEYBOARD_BH);
1131         while (!tty->stopped && count) {
1132                 c = from_user ? get_fs_byte(buf) : *buf;
1133                 buf++; n++; count--;
1134                 if (vc_state == ESnormal
1135                 && (c >= 32 || (disp_ctrl && (c&0x7f) != 27))
1136                 && (toggle_meta ? translate[c|0x80] : translate[c])) {
1137                         if (toggle_meta)
1138                                 c |= 0x80;
1139                         if (need_wrap) {
1140                                 cr(currcons);
1141                                 lf(currcons);
1142                         }
1143                         if (decim)
1144                                 insert_char(currcons);
1145                         c = translate[c];
1146                         *(unsigned short *) pos = (attr << 8) + c;
1147                         if (x == video_num_columns - 1)
1148                                 need_wrap = decawm;
1149                         else {
1150                                 x++;
1151                                 pos+=2;
1152                         }
1153                         continue;
1154                 }
1155 
1156                 /*
1157                  *  Control characters can be used in the _middle_
1158                  *  of an escape sequence.
1159                  */
1160                 switch (c) {
1161                         case 7:
1162                                 kd_mksound(0x637, HZ/8);
1163                                 continue;
1164                         case 8:
1165                                 bs(currcons);
1166                                 continue;
1167                         case 9:
1168                                 pos -= (x << 1);
1169                                 while (x < video_num_columns - 1) {
1170                                         x++;
1171                                         if (tab_stop[x >> 5] & (1 << (x & 31)))
1172                                                 break;
1173                                 }
1174                                 pos += (x << 1);
1175                                 continue;
1176                         case 10: case 11: case 12:
1177                                 lf(currcons);
1178                                 if (!is_kbd(lnm))
1179                                         continue;
1180                         case 13:
1181                                 cr(currcons);
1182                                 continue;
1183                         case 14:
1184                                 charset = 1;
1185                                 translate = G1_charset;
1186                                 continue;
1187                         case 15:
1188                                 charset = 0;
1189                                 translate = G0_charset;
1190                                 continue;
1191                         case 24: case 26:
1192                                 vc_state = ESnormal;
1193                                 continue;
1194                         case 27:
1195                                 vc_state = ESesc;
1196                                 continue;
1197                         case 127:
1198                                 del(currcons);
1199                                 continue;
1200                         case 128+27:
1201                                 vc_state = ESsquare;
1202                                 continue;
1203                 }
1204                 switch(vc_state) {
1205                         case ESesc:
1206                                 vc_state = ESnormal;
1207                                 switch (c) {
1208                                   case '[':
1209                                         vc_state = ESsquare;
1210                                         continue;
1211                                   case 'E':
1212                                         cr(currcons);
1213                                         lf(currcons);
1214                                         continue;
1215                                   case 'M':
1216                                         ri(currcons);
1217                                         continue;
1218                                   case 'D':
1219                                         lf(currcons);
1220                                         continue;
1221                                   case 'H':
1222                                         tab_stop[x >> 5] |= (1 << (x & 31));
1223                                         continue;
1224                                   case 'Z':
1225                                         respond_ID(currcons,tty);
1226                                         continue;
1227                                   case '7':
1228                                         save_cur(currcons);
1229                                         continue;
1230                                   case '8':
1231                                         restore_cur(currcons);
1232                                         continue;
1233                                   case '(':
1234                                         vc_state = ESsetG0;
1235                                         continue;
1236                                   case ')':
1237                                         vc_state = ESsetG1;
1238                                         continue;
1239                                   case '#':
1240                                         vc_state = EShash;
1241                                         continue;
1242                                   case 'c':
1243                                         reset_terminal(currcons,1);
1244                                         continue;
1245                                   case '>':  /* Numeric keypad */
1246                                         clr_kbd(kbdapplic);
1247                                         continue;
1248                                   case '=':  /* Appl. keypad */
1249                                         set_kbd(kbdapplic);
1250                                         continue;
1251                                 }       
1252                                 continue;
1253                         case ESsquare:
1254                                 for(npar = 0 ; npar < NPAR ; npar++)
1255                                         par[npar] = 0;
1256                                 npar = 0;
1257                                 vc_state = ESgetpars;
1258                                 if (c == '[') { /* Function key */
1259                                         vc_state=ESfunckey;
1260                                         continue;
1261                                 }
1262                                 ques = (c=='?');
1263                                 if (ques)
1264                                         continue;
1265                         case ESgetpars:
1266                                 if (c==';' && npar<NPAR-1) {
1267                                         npar++;
1268                                         continue;
1269                                 } else if (c>='0' && c<='9') {
1270                                         par[npar] *= 10;
1271                                         par[npar] += c-'0';
1272                                         continue;
1273                                 } else vc_state=ESgotpars;
1274                         case ESgotpars:
1275                                 vc_state = ESnormal;
1276                                 switch(c) {
1277                                         case 'h':
1278                                                 set_mode(currcons,1);
1279                                                 continue;
1280                                         case 'l':
1281                                                 set_mode(currcons,0);
1282                                                 continue;
1283                                         case 'n':
1284                                                 if (!ques)
1285                                                         if (par[0] == 5)
1286                                                                 status_report(currcons,tty);
1287                                                         else if (par[0] == 6)
1288                                                                 cursor_report(currcons,tty);
1289                                                 continue;
1290                                 }
1291                                 if (ques) {
1292                                         ques = 0;
1293                                         continue;
1294                                 }
1295                                 switch(c) {
1296                                         case 'G': case '`':
1297                                                 if (par[0]) par[0]--;
1298                                                 gotoxy(currcons,par[0],y);
1299                                                 continue;
1300                                         case 'A':
1301                                                 if (!par[0]) par[0]++;
1302                                                 gotoxy(currcons,x,y-par[0]);
1303                                                 continue;
1304                                         case 'B': case 'e':
1305                                                 if (!par[0]) par[0]++;
1306                                                 gotoxy(currcons,x,y+par[0]);
1307                                                 continue;
1308                                         case 'C': case 'a':
1309                                                 if (!par[0]) par[0]++;
1310                                                 gotoxy(currcons,x+par[0],y);
1311                                                 continue;
1312                                         case 'D':
1313                                                 if (!par[0]) par[0]++;
1314                                                 gotoxy(currcons,x-par[0],y);
1315                                                 continue;
1316                                         case 'E':
1317                                                 if (!par[0]) par[0]++;
1318                                                 gotoxy(currcons,0,y+par[0]);
1319                                                 continue;
1320                                         case 'F':
1321                                                 if (!par[0]) par[0]++;
1322                                                 gotoxy(currcons,0,y-par[0]);
1323                                                 continue;
1324                                         case 'd':
1325                                                 if (par[0]) par[0]--;
1326                                                 gotoxy(currcons,x,par[0]);
1327                                                 continue;
1328                                         case 'H': case 'f':
1329                                                 if (par[0]) par[0]--;
1330                                                 if (par[1]) par[1]--;
1331                                                 gotoxy(currcons,par[1],par[0]);
1332                                                 continue;
1333                                         case 'J':
1334                                                 csi_J(currcons,par[0]);
1335                                                 continue;
1336                                         case 'K':
1337                                                 csi_K(currcons,par[0]);
1338                                                 continue;
1339                                         case 'L':
1340                                                 csi_L(currcons,par[0]);
1341                                                 continue;
1342                                         case 'M':
1343                                                 csi_M(currcons,par[0]);
1344                                                 continue;
1345                                         case 'P':
1346                                                 csi_P(currcons,par[0]);
1347                                                 continue;
1348                                         case 'c':
1349                                                 if (!par[0])
1350                                                         respond_ID(currcons,tty);
1351                                                 continue;
1352                                         case 'g':
1353                                                 if (!par[0])
1354                                                         tab_stop[x >> 5] &= ~(1 << (x & 31));
1355                                                 else if (par[0] == 3) {
1356                                                         tab_stop[0] =
1357                                                         tab_stop[1] =
1358                                                         tab_stop[2] =
1359                                                         tab_stop[3] =
1360                                                         tab_stop[4] = 0;
1361                                                 }
1362                                                 continue;
1363                                         case 'm':
1364                                                 csi_m(currcons);
1365                                                 continue;
1366                                         case 'r':
1367                                                 if (!par[0])
1368                                                         par[0]++;
1369                                                 if (!par[1])
1370                                                         par[1] = video_num_lines;
1371                                                 /* Minimum allowed region is 2 lines */
1372                                                 if (par[0] < par[1] &&
1373                                                     par[1] <= video_num_lines) {
1374                                                         top=par[0]-1;
1375                                                         bottom=par[1];
1376                                                         gotoxy(currcons,0,0);
1377                                                 }
1378                                                 continue;
1379                                         case 's':
1380                                                 save_cur(currcons);
1381                                                 continue;
1382                                         case 'u':
1383                                                 restore_cur(currcons);
1384                                                 continue;
1385                                         case 'X':
1386                                                 csi_X(currcons, par[0]);
1387                                                 continue;
1388                                         case '@':
1389                                                 csi_at(currcons,par[0]);
1390                                                 continue;
1391                                         case ']': /* setterm functions */
1392                                                 setterm_command(currcons);
1393                                                 continue;
1394                                 }
1395                                 continue;
1396                         case ESfunckey:
1397                                 vc_state = ESnormal;
1398                                 continue;
1399                         case EShash:
1400                                 vc_state = ESnormal;
1401                                 if (c == '8') {
1402                                         /* DEC screen alignment test. kludge :-) */
1403                                         video_erase_char =
1404                                                 (video_erase_char & 0xff00) | 'E';
1405                                         csi_J(currcons, 2);
1406                                         video_erase_char =
1407                                                 (video_erase_char & 0xff00) | ' ';
1408                                 }
1409                                 continue;
1410                         case ESsetG0:
1411                                 if (c == '0')
1412                                         G0_charset = GRAF_TRANS;
1413                                 else if (c == 'B')
1414                                         G0_charset = NORM_TRANS;
1415                                 else if (c == 'U')
1416                                         G0_charset = NULL_TRANS;
1417                                 else if (c == 'K')
1418                                         G0_charset = USER_TRANS;
1419                                 if (charset == 0)
1420                                         translate = G0_charset;
1421                                 vc_state = ESnormal;
1422                                 continue;
1423                         case ESsetG1:
1424                                 if (c == '0')
1425                                         G1_charset = GRAF_TRANS;
1426                                 else if (c == 'B')
1427                                         G1_charset = NORM_TRANS;
1428                                 else if (c == 'U')
1429                                         G1_charset = NULL_TRANS;
1430                                 else if (c == 'K')
1431                                         G1_charset = USER_TRANS;
1432                                 if (charset == 1)
1433                                         translate = G1_charset;
1434                                 vc_state = ESnormal;
1435                                 continue;
1436                         default:
1437                                 vc_state = ESnormal;
1438                 }
1439         }
1440         if (vcmode != KD_GRAPHICS)
1441                 set_cursor(currcons);
1442         enable_bh(KEYBOARD_BH);
1443         return n;
1444 }
1445 
1446 static int con_write_room(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
1447 {
1448         if (tty->stopped)
1449                 return 0;
1450         return 4096;            /* No limit, really; we're not buffering */
1451 }
1452 
1453 static int con_chars_in_buffer(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
1454 {
1455         return 0;               /* we're not buffering */
1456 }
1457 
1458 void poke_blanked_console(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1459 {
1460         timer_active &= ~(1<<BLANK_TIMER);
1461         if (vt_cons[fg_console].vc_mode == KD_GRAPHICS)
1462                 return;
1463         if (console_blanked) {
1464                 timer_table[BLANK_TIMER].expires = 0;
1465                 timer_active |= 1<<BLANK_TIMER;
1466         } else if (blankinterval) {
1467                 timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
1468                 timer_active |= 1<<BLANK_TIMER;
1469         }
1470 }
1471 
1472 void * memsetw(void * s, unsigned short c, unsigned int count)
     /* [previous][next][first][last][top][bottom][index][help] */
1473 {
1474 __asm__("cld\n\t"
1475         "rep\n\t"
1476         "stosw"
1477         : /* no output */
1478         :"a" (c),"D" (s),"c" (count/2)
1479         :"cx","di");
1480 return s;
1481 }
1482 
1483 void console_print(const char * b)
     /* [previous][next][first][last][top][bottom][index][help] */
1484 {
1485         int currcons = fg_console;
1486         unsigned char c;
1487 
1488         if (!printable || currcons<0 || currcons>=NR_CONSOLES)
1489                 return;
1490         while ((c = *(b++)) != 0) {
1491                 if (c == 10 || c == 13 || need_wrap) {
1492                         if (c != 13)
1493                                 lf(currcons);
1494                         cr(currcons);
1495                         if (c == 10 || c == 13)
1496                                 continue;
1497                 }
1498                 *(unsigned short *) pos = (attr << 8) + c;
1499                 if (x == video_num_columns - 1) {
1500                         need_wrap = 1;
1501                         continue;
1502                 }
1503                 x++;
1504                 pos+=2;
1505         }
1506         set_cursor(currcons);
1507         if (vt_cons[fg_console].vc_mode == KD_GRAPHICS)
1508                 return;
1509         timer_active &= ~(1<<BLANK_TIMER);
1510         if (console_blanked) {
1511                 timer_table[BLANK_TIMER].expires = 0;
1512                 timer_active |= 1<<BLANK_TIMER;
1513         } else if (blankinterval) {
1514                 timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
1515                 timer_active |= 1<<BLANK_TIMER;
1516         }
1517 }
1518 
1519 /*
1520  * con_throttle and con_unthrottle are only used for
1521  * paste_selection(), which has to stuff in a large number of
1522  * characters...
1523  */
1524 static void con_throttle(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
1525 {
1526 }
1527 
1528 static void con_unthrottle(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
1529 {
1530         struct vt_struct *vt = (struct vt_struct *) tty->driver_data;
1531 
1532         wake_up_interruptible(&vt->paste_wait);
1533 }
1534 
1535 /*
1536  *  long con_init(long);
1537  *
1538  * This routine initializes console interrupts, and does nothing
1539  * else. If you want the screen to clear, call tty_write with
1540  * the appropriate escape-sequence.
1541  *
1542  * Reads the information preserved by setup.s to determine the current display
1543  * type and sets everything accordingly.
1544  */
1545 long con_init(long kmem_start)
     /* [previous][next][first][last][top][bottom][index][help] */
1546 {
1547         char *display_desc = "????";
1548         int currcons = 0;
1549         long base;
1550         int orig_x = ORIG_X;
1551         int orig_y = ORIG_Y;
1552 
1553         memset(&console_driver, 0, sizeof(struct tty_driver));
1554         console_driver.magic = TTY_DRIVER_MAGIC;
1555         console_driver.name = "tty";
1556         console_driver.name_base = 1;
1557         console_driver.major = TTY_MAJOR;
1558         console_driver.minor_start = 1;
1559         console_driver.num = NR_CONSOLES;
1560         console_driver.type = TTY_DRIVER_TYPE_CONSOLE;
1561         console_driver.init_termios = tty_std_termios;
1562         console_driver.flags = TTY_DRIVER_REAL_RAW;
1563         console_driver.refcount = &console_refcount;
1564         console_driver.table = console_table;
1565         console_driver.termios = console_termios;
1566         console_driver.termios_locked = console_termios_locked;
1567 
1568         console_driver.open = con_open;
1569         console_driver.write = con_write;
1570         console_driver.write_room = con_write_room;
1571         console_driver.chars_in_buffer = con_chars_in_buffer;
1572         console_driver.ioctl = vt_ioctl;
1573         console_driver.stop = con_stop;
1574         console_driver.start = con_start;
1575         console_driver.throttle = con_throttle;
1576         console_driver.unthrottle = con_unthrottle;
1577         
1578         if (tty_register_driver(&console_driver))
1579                 panic("Couldn't register console driver\n");
1580         
1581         vc_scrmembuf = (unsigned short *) kmem_start;
1582         video_num_columns = ORIG_VIDEO_COLS;
1583         video_size_row = video_num_columns * 2;
1584         video_num_lines = ORIG_VIDEO_LINES;
1585         video_page = ORIG_VIDEO_PAGE;
1586         screen_size = (video_num_lines * video_size_row);
1587         kmem_start += NR_CONSOLES * screen_size;
1588         timer_table[BLANK_TIMER].fn = blank_screen;
1589         timer_table[BLANK_TIMER].expires = 0;
1590         if (blankinterval) {
1591                 timer_table[BLANK_TIMER].expires = jiffies+blankinterval;
1592                 timer_active |= 1<<BLANK_TIMER;
1593         }
1594         
1595         if (ORIG_VIDEO_MODE == 7)       /* Is this a monochrome display? */
1596         {
1597                 video_mem_base = 0xb0000;
1598                 video_port_reg = 0x3b4;
1599                 video_port_val = 0x3b5;
1600                 if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
1601                 {
1602                         video_type = VIDEO_TYPE_EGAM;
1603                         video_mem_term = 0xb8000;
1604                         display_desc = "EGA+";
1605                 }
1606                 else
1607                 {
1608                         video_type = VIDEO_TYPE_MDA;
1609                         video_mem_term = 0xb2000;
1610                         display_desc = "*MDA";
1611                 }
1612         }
1613         else                            /* If not, it is color. */
1614         {
1615                 can_do_color = 1;
1616                 video_mem_base = 0xb8000;
1617                 video_port_reg  = 0x3d4;
1618                 video_port_val  = 0x3d5;
1619                 if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
1620                 {
1621                         video_type = VIDEO_TYPE_EGAC;
1622                         video_mem_term = 0xc0000;
1623                         display_desc = "EGA+";
1624                 }
1625                 else
1626                 {
1627                         video_type = VIDEO_TYPE_CGA;
1628                         video_mem_term = 0xba000;
1629                         display_desc = "*CGA";
1630                 }
1631         }
1632         
1633         /* Initialize the variables used for scrolling (mostly EGA/VGA) */
1634 
1635         base = (long)vc_scrmembuf;
1636         for (currcons = 0; currcons<NR_CONSOLES; currcons++) {
1637                 pos = origin = video_mem_start = base;
1638                 scr_end = video_mem_end = (base += screen_size);
1639                 vc_scrbuf[currcons] = (unsigned short *) origin;
1640                 vcmode          = KD_TEXT;
1641                 vtmode.mode     = VT_AUTO;
1642                 vtmode.waitv    = 0;
1643                 vtmode.relsig   = 0;
1644                 vtmode.acqsig   = 0;
1645                 vtmode.frsig    = 0;
1646                 vtpid           = -1;
1647                 vtnewvt         = -1;
1648                 clr_kbd(kbdraw);
1649                 def_color       = 0x07;   /* white */
1650                 ulcolor         = 0x0f;   /* bold white */
1651                 halfcolor       = 0x08;   /* grey */
1652                 vt_cons[currcons].paste_wait = 0;
1653                 reset_terminal(currcons, currcons);
1654         }
1655         currcons = fg_console = 0;
1656 
1657         video_mem_start = video_mem_base;
1658         video_mem_end = video_mem_term;
1659         origin = video_mem_start;
1660         scr_end = video_mem_start + video_num_lines * video_size_row;
1661         gotoxy(currcons,0,0);
1662         save_cur(currcons);
1663         gotoxy(currcons,orig_x,orig_y);
1664         update_screen(fg_console);
1665         printable = 1;
1666         printk("Console: %s %s %ldx%ld, %d virtual consoles\n",
1667                 can_do_color?"colour":"mono",
1668                 display_desc,
1669                 video_num_columns,video_num_lines,
1670                 NR_CONSOLES);
1671         register_console(console_print);
1672         return kmem_start;
1673 }
1674 
1675 /*
1676  * kbdsave doesn't need to do anything: it's all handled automatically
1677  * with the new data structures..
1678  */
1679 void kbdsave(int new_console)
     /* [previous][next][first][last][top][bottom][index][help] */
1680 {
1681 }
1682 
1683 static void get_scrmem(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
1684 {
1685         memcpy((void *)vc_scrbuf[currcons],(void *)origin, screen_size);
1686         video_mem_start = (unsigned long)vc_scrbuf[currcons];
1687         origin  = video_mem_start;
1688         scr_end = video_mem_end = video_mem_start+screen_size;
1689         pos = origin + y*video_size_row + (x<<1);
1690 }
1691 
1692 static void set_scrmem(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
1693 {
1694 #ifdef CONFIG_HGA
1695   /* This works with XFree86 1.2, 1.3 and 2.0
1696      This code could be extended and made more generally useful if we could
1697      determine the actual video mode. It appears that this should be
1698      possible on a genuine Hercules card, but I (WM) haven't been able to
1699      read from any of the required registers on my clone card.
1700      */
1701         /* This code should work with Hercules and MDA cards. */
1702         if (video_type == VIDEO_TYPE_MDA)
1703           {
1704             if (vcmode == KD_TEXT)
1705               {
1706                 /* Ensure that the card is in text mode. */
1707                 int     i;
1708                 static char herc_txt_tbl[12] = {
1709                   0x61,0x50,0x52,0x0f,0x19,6,0x19,0x19,2,0x0d,0x0b,0x0c };
1710                 outb_p(0, 0x3bf);  /* Back to power-on defaults */
1711                 outb_p(0, 0x3b8);  /* Blank the screen, select page 0, etc */
1712                 for ( i = 0 ; i < 12 ; i++ )
1713                   {
1714                     outb_p(i, 0x3b4);
1715                     outb_p(herc_txt_tbl[i], 0x3b5);
1716                   }
1717               }
1718 #define HGA_BLINKER_ON 0x20
1719 #define HGA_SCREEN_ON  8
1720             /* Make sure that the hardware is not blanked */
1721             outb_p(HGA_BLINKER_ON | HGA_SCREEN_ON, 0x3b8);
1722           }
1723 #endif CONFIG_HGA
1724 
1725         video_mem_start = video_mem_base;
1726         video_mem_end = video_mem_term;
1727         origin  = video_mem_start;
1728         scr_end = video_mem_start + screen_size;
1729         pos = origin + y*video_size_row + (x<<1);
1730         memcpy((void *)video_mem_base, (void *)vc_scrbuf[fg_console], screen_size);
1731 }
1732 
1733 void blank_screen(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1734 {
1735         if (console_blanked)
1736                 return;
1737         timer_table[BLANK_TIMER].fn = unblank_screen;
1738         get_scrmem(fg_console);
1739         hide_cursor();
1740         console_blanked = 1;
1741         memsetw((void *)video_mem_base, 0x0020, video_mem_term-video_mem_base );
1742 }
1743 
1744 void unblank_screen(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1745 {
1746         if (!console_blanked)
1747                 return;
1748         timer_table[BLANK_TIMER].fn = blank_screen;
1749         if (blankinterval) {
1750                 timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
1751                 timer_active |= 1<<BLANK_TIMER;
1752         }
1753         console_blanked = 0;
1754         set_scrmem(fg_console);
1755         set_origin(fg_console);
1756         set_cursor(fg_console);
1757 }
1758 
1759 void update_screen(int new_console)
     /* [previous][next][first][last][top][bottom][index][help] */
1760 {
1761         static int lock = 0;
1762 
1763         if (new_console == fg_console || lock)
1764                 return;
1765         lock = 1;
1766         kbdsave(new_console);
1767 #ifdef CONFIG_SELECTION
1768         highlight_pointer(fg_console,-1);
1769 #endif /* CONFIG_SELECTION */
1770         get_scrmem(fg_console); 
1771         fg_console = new_console;
1772         set_scrmem(fg_console); 
1773         set_origin(fg_console);
1774         set_cursor(new_console);
1775         set_leds();
1776         compute_shiftstate();
1777         lock = 0;
1778 }
1779 
1780 int do_screendump(int arg)
     /* [previous][next][first][last][top][bottom][index][help] */
1781 {
1782         char *sptr, *buf = (char *)arg;
1783         int currcons, l;
1784 
1785         if (!suser())
1786                 return -EPERM;
1787         l = verify_area(VERIFY_WRITE, buf,2+video_num_columns*video_num_lines);
1788         if (l)
1789                 return l;
1790         currcons = get_fs_byte(buf+1);
1791         if ((currcons<0) || (currcons>NR_CONSOLES))
1792                 return -EIO;
1793         put_fs_byte((char)(video_num_lines),buf++);     
1794         put_fs_byte((char)(video_num_columns),buf++);
1795         currcons = (currcons ? currcons-1 : fg_console);
1796         sptr = (char *) origin;
1797         for (l=video_num_lines*video_num_columns; l>0 ; l--, sptr++)
1798                 put_fs_byte(*sptr++,buf++);     
1799         return(0);
1800 }
1801 
1802 /*
1803  * Later on maybe we'll dynamically allocate the console screen
1804  * memory.
1805  */
1806 int con_open(struct tty_struct *tty, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
1807 {
1808         int     idx;
1809 
1810         idx = MINOR(tty->device) - tty->driver.minor_start;
1811         
1812         if (idx > NR_CONSOLES)
1813                 return -ENODEV;
1814         vt_cons[idx].vc_num = idx;
1815         tty->driver_data = &vt_cons[idx];
1816         
1817         if (!tty->winsize.ws_row && !tty->winsize.ws_col) {
1818                 tty->winsize.ws_row = video_num_lines;
1819                 tty->winsize.ws_col = video_num_columns;
1820         }
1821         return 0;
1822 }
1823 
1824 #ifdef CONFIG_SELECTION
1825 /* correction factor for when screen is hardware-scrolled */
1826 #define hwscroll_offset (currcons == fg_console ? ((__real_origin - __origin) << 1) : 0)
1827 
1828 /* set reverse video on characters s-e of console with selection. */
1829 static void highlight(const int currcons, const int s, const int e)
     /* [previous][next][first][last][top][bottom][index][help] */
1830 {
1831         unsigned char *p, *p1, *p2;
1832 
1833         p1 = (unsigned char *)origin - hwscroll_offset + s + 1;
1834         p2 = (unsigned char *)origin - hwscroll_offset + e + 1;
1835         if (p1 > p2)
1836         {
1837                 p = p1;
1838                 p1 = p2;
1839                 p2 = p;
1840         }
1841         for (p = p1; p <= p2; p += 2)
1842                 *p = (*p & 0x88) | ((*p << 4) & 0x70) | ((*p >> 4) & 0x07);
1843 }
1844 
1845 /* use complementary color to show the pointer */
1846 static void highlight_pointer(const int currcons, const int where)
     /* [previous][next][first][last][top][bottom][index][help] */
1847 {
1848         unsigned char *p;
1849         static unsigned char *prev=NULL;
1850 
1851         if (where==-1) /* remove the pointer */
1852         {
1853                 if (prev)
1854                 {
1855                         *prev ^= 0x77;
1856                         prev=NULL;
1857                 }
1858         }
1859         else
1860         {
1861                 p = (unsigned char *)origin - hwscroll_offset + where + 1;
1862                 *p ^= 0x77;
1863                 if (prev) *prev ^= 0x77; /* remove the previous one */
1864                 prev=p;
1865         }
1866 }
1867 
1868 
1869 /*
1870  * This function uses a 128-bit look up table
1871  */
1872 static unsigned long inwordLut[4]={
1873   0x00000000, /* control chars     */
1874   0x03FF0000, /* digits            */
1875   0x87FFFFFE, /* uppercase and '_' */
1876   0x07FFFFFE  /* lowercase         */
1877 };
1878 static inline int inword(const char c) {
     /* [previous][next][first][last][top][bottom][index][help] */
1879    return ( inwordLut[(c>>5)&3] >> (c&0x1F) ) & 1;
1880 }
1881 
1882 /* set inwordLut contents. Invoked by ioctl(). */
1883 int sel_loadlut(const int arg)
     /* [previous][next][first][last][top][bottom][index][help] */
1884 {
1885     memcpy_fromfs(inwordLut,(unsigned long *)(arg+4),16);
1886     return 0;
1887 }
1888 
1889 /* does screen address p correspond to character at LH/RH edge of screen? */
1890 static inline int atedge(const int p)
     /* [previous][next][first][last][top][bottom][index][help] */
1891 {
1892         return (!(p % video_size_row) || !((p + 2) % video_size_row));
1893 }
1894 
1895 /* constrain v such that l <= v <= u */
1896 static inline short limit(const int v, const int l, const int u)
     /* [previous][next][first][last][top][bottom][index][help] */
1897 {
1898         return (v < l) ? l : ((v > u) ? u : v);
1899 }
1900 
1901 /* invoked via ioctl(TIOCLINUX) */
1902 int mouse_reporting(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1903 {
1904         int currcons = fg_console;
1905 
1906         return report_mouse;
1907 }
1908 
1909 /* set the current selection. Invoked by ioctl(). */
1910 int set_selection(const int arg, struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
1911 {
1912         unsigned short *args, xs, ys, xe, ye;
1913         int currcons = fg_console;
1914         int sel_mode, new_sel_start, new_sel_end, spc;
1915         char *bp, *obp, *spos;
1916         int i, ps, pe;
1917         char *off = (char *)origin - hwscroll_offset;
1918 
1919         unblank_screen();
1920         args = (unsigned short *)(arg + 1);
1921         xs = get_fs_word(args++) - 1;
1922         ys = get_fs_word(args++) - 1;
1923         xe = get_fs_word(args++) - 1;
1924         ye = get_fs_word(args++) - 1;
1925         sel_mode = get_fs_word(args);
1926 
1927         xs = limit(xs, 0, video_num_columns - 1);
1928         ys = limit(ys, 0, video_num_lines - 1);
1929         xe = limit(xe, 0, video_num_columns - 1);
1930         ye = limit(ye, 0, video_num_lines - 1);
1931         ps = ys * video_size_row + (xs << 1);
1932         pe = ye * video_size_row + (xe << 1);
1933 
1934         if (report_mouse && (sel_mode & 16)) {
1935                 mouse_report(currcons, tty, sel_mode & 15, xs, ys);
1936                 return 0;
1937         }
1938 
1939         if (ps > pe)    /* make sel_start <= sel_end */
1940         {
1941                 int tmp = ps;
1942                 ps = pe;
1943                 pe = tmp;
1944         }
1945 
1946         switch (sel_mode)
1947         {
1948                 case 0: /* character-by-character selection */
1949                         new_sel_start = ps;
1950                         new_sel_end = pe;
1951                         break;
1952                 case 1: /* word-by-word selection */
1953                         spc = isspace(*(off + ps));
1954                         for (new_sel_start = ps; ; ps -= 2)
1955                         {
1956                                 if ((spc && !isspace(*(off + ps))) ||
1957                                     (!spc && !inword(*(off + ps))))
1958                                         break;
1959                                 new_sel_start = ps;
1960                                 if (!(ps % video_size_row))
1961                                         break;
1962                         }
1963                         spc = isspace(*(off + pe));
1964                         for (new_sel_end = pe; ; pe += 2)
1965                         {
1966                                 if ((spc && !isspace(*(off + pe))) ||
1967                                     (!spc && !inword(*(off + pe))))
1968                                         break;
1969                                 new_sel_end = pe;
1970                                 if (!((pe + 2) % video_size_row))
1971                                         break;
1972                         }
1973                         break;
1974                 case 2: /* line-by-line selection */
1975                         new_sel_start = ps - ps % video_size_row;
1976                         new_sel_end = pe + video_size_row
1977                                     - pe % video_size_row - 2;
1978                         break;
1979                 case 3: /* pointer highlight */
1980                         if (sel_cons != currcons)
1981                         {
1982                                 highlight_pointer(sel_cons,-1);
1983                                 clear_selection();
1984                                 sel_cons = currcons;
1985                         }
1986                         highlight_pointer(sel_cons,pe);
1987                         return 0; /* nothing more */
1988                 default:
1989                         return -EINVAL;
1990         }
1991         /* select to end of line if on trailing space */
1992         if (new_sel_end > new_sel_start &&
1993                 !atedge(new_sel_end) && isspace(*(off + new_sel_end)))
1994         {
1995                 for (pe = new_sel_end + 2; ; pe += 2)
1996                 {
1997                         if (!isspace(*(off + pe)) || atedge(pe))
1998                                 break;
1999                 }
2000                 if (isspace(*(off + pe)))
2001                         new_sel_end = pe;
2002         }
2003         if (sel_cons != currcons)
2004         {
2005                 clear_selection();
2006                 sel_cons = currcons;
2007         }
2008         if (sel_start == -1)    /* no current selection */
2009                 highlight(sel_cons, new_sel_start, new_sel_end);
2010         else if (new_sel_start == sel_start)
2011         {
2012                 if (new_sel_end == sel_end)     /* no action required */
2013                         return 0;
2014                 else if (new_sel_end > sel_end) /* extend to right */
2015                         highlight(sel_cons, sel_end + 2, new_sel_end);
2016                 else                            /* contract from right */
2017                         highlight(sel_cons, new_sel_end + 2, sel_end);
2018         }
2019         else if (new_sel_end == sel_end)
2020         {
2021                 if (new_sel_start < sel_start)  /* extend to left */
2022                         highlight(sel_cons, new_sel_start, sel_start - 2);
2023                 else                            /* contract from left */
2024                         highlight(sel_cons, sel_start, new_sel_start - 2);
2025         }
2026         else    /* some other case; start selection from scratch */
2027         {
2028                 clear_selection();
2029                 highlight(sel_cons, new_sel_start, new_sel_end);
2030         }
2031         sel_start = new_sel_start;
2032         sel_end = new_sel_end;
2033         obp = bp = sel_buffer;
2034         for (i = sel_start; i <= sel_end; i += 2)
2035         {
2036                 spos = (char *)off + i;
2037                 *bp++ = *spos;
2038                 if (!isspace(*spos))
2039                         obp = bp;
2040                 if (! ((i + 2) % video_size_row))
2041                 {
2042                         /* strip trailing blanks from line and add newline,
2043                            unless non-space at end of line. */
2044                         if (obp != bp)
2045                         {
2046                                 bp = obp;
2047                                 *bp++ = '\r';
2048                         }
2049                         obp = bp;
2050                 }
2051                 /* check for space, leaving room for next character, possible
2052                    newline, and null at end. */
2053                 if (bp - sel_buffer > SEL_BUFFER_SIZE - 3)
2054                         break;
2055         }
2056         *bp = '\0';
2057         return 0;
2058 }
2059 
2060 /* insert the contents of the selection buffer into the queue of the
2061    tty associated with the current console. Invoked by ioctl(). */
2062 int paste_selection(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
2063 {
2064         struct wait_queue wait = { current, NULL };
2065         char    *bp = sel_buffer;
2066         int     c, l;
2067         struct vt_struct *vt = (struct vt_struct *) tty->driver_data;
2068         
2069         if (!sel_buffer[0])
2070                 return 0;
2071         unblank_screen();
2072         c = strlen(sel_buffer);
2073         current->state = TASK_INTERRUPTIBLE;
2074         add_wait_queue(&vt->paste_wait, &wait);
2075         while (c) {
2076                 if (test_bit(TTY_THROTTLED, &tty->flags)) {
2077                         schedule();
2078                         continue;
2079                 }
2080                 l = MIN(c, tty->ldisc.receive_room(tty));
2081                 tty->ldisc.receive_buf(tty, bp, 0, l);
2082                 c -= l;
2083                 bp += l;
2084         }
2085         current->state = TASK_RUNNING;
2086         return 0;
2087 }
2088 
2089 /* remove the current selection highlight, if any, from the console holding
2090    the selection. */
2091 static void clear_selection()
     /* [previous][next][first][last][top][bottom][index][help] */
2092 {
2093         highlight_pointer(sel_cons, -1); /* hide the pointer */
2094         if (sel_start != -1)
2095         {
2096                 highlight(sel_cons, sel_start, sel_end);
2097                 sel_start = -1;
2098         }
2099 }
2100 #endif /* CONFIG_SELECTION */
2101 
2102 /*
2103  * PIO_FONT support.
2104  *
2105  * The font loading code goes back to the codepage package by
2106  * Joel Hoffman (joel@wam.umd.edu). (He reports that the original
2107  * reference is: "From: p. 307 of _Programmer's Guide to PC & PS/2
2108  * Video Systems_ by Richard Wilton. 1987.  Microsoft Press".)
2109  *
2110  * Change for certain monochrome monitors by Yury Shevchuck
2111  * (sizif@botik.yaroslavl.su).
2112  */
2113 
2114 #define colourmap ((char *)0xa0000)
2115 /* Pauline Middelink reports that we should use 0xA0000 for the bwmap as well.. */
2116 #define blackwmap ((char *)0xa0000)
2117 #define cmapsz 8192
2118 #define seq_port_reg (0x3c4)
2119 #define seq_port_val (0x3c5)
2120 #define gr_port_reg (0x3ce)
2121 #define gr_port_val (0x3cf)
2122 
2123 static int set_get_font(char * arg, int set)
     /* [previous][next][first][last][top][bottom][index][help] */
2124 {
2125 #ifdef CAN_LOAD_EGA_FONTS
2126         int i;
2127         char *charmap;
2128         int beg;
2129 
2130         /* no use to "load" CGA... */
2131 
2132         if (video_type == VIDEO_TYPE_EGAC) {
2133                 charmap = colourmap;
2134                 beg = 0x0e;
2135         } else if (video_type == VIDEO_TYPE_EGAM) {
2136                 charmap = blackwmap;
2137                 beg = 0x0a;
2138         } else
2139                 return -EINVAL;
2140 
2141         i = verify_area(set ? VERIFY_READ : VERIFY_WRITE, (void *)arg, cmapsz);
2142         if (i)
2143                 return i;
2144 
2145         cli();
2146         outb_p( 0x00, seq_port_reg );   /* First, the sequencer */
2147         outb_p( 0x01, seq_port_val );   /* Synchronous reset */
2148         outb_p( 0x02, seq_port_reg );
2149         outb_p( 0x04, seq_port_val );   /* CPU writes only to map 2 */
2150         outb_p( 0x04, seq_port_reg );
2151         outb_p( 0x07, seq_port_val );   /* Sequential addressing */
2152         outb_p( 0x00, seq_port_reg );
2153         outb_p( 0x03, seq_port_val );   /* Clear synchronous reset */
2154 
2155         outb_p( 0x04, gr_port_reg );    /* Now, the graphics controller */
2156         outb_p( 0x02, gr_port_val );    /* select map 2 */
2157         outb_p( 0x05, gr_port_reg );
2158         outb_p( 0x00, gr_port_val );    /* disable odd-even addressing */
2159         outb_p( 0x06, gr_port_reg );
2160         outb_p( 0x00, gr_port_val );    /* map start at A000:0000 */
2161         sti();
2162 
2163         if (set)
2164                 for (i=0; i<cmapsz ; i++)
2165                         *(charmap+i) = get_fs_byte(arg+i);
2166         else
2167                 for (i=0; i<cmapsz ; i++)
2168                         put_fs_byte(*(charmap+i), arg+i);
2169 
2170         cli();
2171         outb_p( 0x00, seq_port_reg );   /* First, the sequencer */
2172         outb_p( 0x01, seq_port_val );   /* Synchronous reset */
2173         outb_p( 0x02, seq_port_reg );
2174         outb_p( 0x03, seq_port_val );   /* CPU writes to maps 0 and 1 */
2175         outb_p( 0x04, seq_port_reg );
2176         outb_p( 0x03, seq_port_val );   /* odd-even addressing */
2177         outb_p( 0x00, seq_port_reg );
2178         outb_p( 0x03, seq_port_val );   /* clear synchronous reset */
2179 
2180         outb_p( 0x04, gr_port_reg );    /* Now, the graphics controller */
2181         outb_p( 0x00, gr_port_val );    /* select map 0 for CPU */
2182         outb_p( 0x05, gr_port_reg );
2183         outb_p( 0x10, gr_port_val );    /* enable even-odd addressing */
2184         outb_p( 0x06, gr_port_reg );
2185         outb_p( beg, gr_port_val );     /* map starts at b800:0 or b000:0 */
2186         sti();
2187 
2188         return 0;
2189 #else
2190         return -EINVAL;
2191 #endif
2192 }
2193 
2194 /*
2195  * Load font into the EGA/VGA character generator. arg points to a 8192
2196  * byte map, 32 bytes per character. Only first H of them are used for
2197  * 8xH fonts (0 < H <= 32).
2198  */
2199 
2200 int con_set_font (char *arg)
     /* [previous][next][first][last][top][bottom][index][help] */
2201 {
2202         return set_get_font (arg,1);
2203 }
2204 
2205 int con_get_font (char *arg)
     /* [previous][next][first][last][top][bottom][index][help] */
2206 {
2207         return set_get_font (arg,0);
2208 }
2209 
2210 /*
2211  * Load customizable translation table (USER_TRANS[]). All checks are here,
2212  * so we need only include 'return con_set_trans(arg)' in the ioctl handler
2213  * arg points to a 256 byte translation table.
2214  */
2215 int con_set_trans(char * arg)
     /* [previous][next][first][last][top][bottom][index][help] */
2216 {
2217         int i;
2218 
2219         i = verify_area(VERIFY_READ, (void *)arg, E_TABSZ);
2220         if (i)
2221                 return i;
2222 
2223         for (i=0; i<E_TABSZ ; i++) USER_TRANS[i] = get_fs_byte(arg+i);
2224         USER_TRANS[012]=0;
2225         USER_TRANS[014]=0;
2226         USER_TRANS[015]=0;
2227         USER_TRANS[033]=0;
2228         return 0;
2229 }
2230 
2231 int con_get_trans(char * arg)
     /* [previous][next][first][last][top][bottom][index][help] */
2232 {
2233         int i;
2234 
2235         i = verify_area(VERIFY_WRITE, (void *)arg, E_TABSZ);
2236         if (i)
2237                 return i;
2238 
2239         for (i=0; i<E_TABSZ ; i++) put_fs_byte(USER_TRANS[i],arg+i);
2240         return 0;
2241 }

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