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

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