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

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