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. respond_num
  22. cursor_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_write
  40. do_keyboard_interrupt
  41. memsetw
  42. console_print
  43. con_init
  44. kbdsave
  45. get_scrmem
  46. set_scrmem
  47. blank_screen
  48. unblank_screen
  49. update_screen
  50. do_screendump
  51. con_open
  52. highlight
  53. inword
  54. atedge
  55. limit
  56. set_selection
  57. paste_selection
  58. clear_selection

   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  * Hopefully this will be a rather complete VT102 implementation.
  19  *
  20  * Beeping thanks to John T Kohl.
  21  * 
  22  * Virtual Consoles, Screen Blanking, Screen Dumping, Color, Graphics
  23  *   Chars, and VT100 enhancements by Peter MacDonald.
  24  *
  25  * Copy and paste function by Andrew Haylett.
  26  */
  27 
  28 /*
  29  *  NOTE!!! We sometimes disable and enable interrupts for a short while
  30  * (to put a word in video IO), but this will work even for keyboard
  31  * interrupts. We know interrupts aren't enabled when getting a keyboard
  32  * interrupt, as we use trap-gates. Hopefully all is well.
  33  */
  34 
  35 /*
  36  * Code to check for different video-cards mostly by Galen Hunt,
  37  * <g-hunt@ee.utah.edu>
  38  */
  39 
  40 #include <linux/sched.h>
  41 #include <linux/timer.h>
  42 #include <linux/tty.h>
  43 #include <linux/config.h>
  44 #include <linux/kernel.h>
  45 #include <linux/string.h>
  46 #include <linux/errno.h>
  47 #include <linux/kd.h>
  48 #include <linux/keyboard.h>
  49 
  50 #include <asm/io.h>
  51 #include <asm/system.h>
  52 #include <asm/segment.h>
  53 
  54 #include "vt_kern.h"
  55 
  56 #ifdef CONFIG_SELECTION
  57 #include <linux/ctype.h>
  58 
  59 /* Routines for selection control. */
  60 int set_selection(const int arg);
  61 int paste_selection(struct tty_struct *tty);
  62 static void clear_selection(void);
  63 
  64 /* Variables for selection control. */
  65 #define SEL_BUFFER_SIZE TTY_BUF_SIZE
  66 static int sel_cons;
  67 static int sel_start = -1;
  68 static int sel_end;
  69 static char sel_buffer[SEL_BUFFER_SIZE] = { '\0' };
  70 #endif /* CONFIG_SELECTION */
  71 
  72 #define NPAR 16
  73 
  74 extern void vt_init(void);
  75 extern void register_console(void (*proc)(const char *));
  76 extern void compute_shiftstate(void);
  77 
  78 unsigned long   video_num_columns;              /* Number of text columns       */
  79 unsigned long   video_num_lines;                /* Number of text lines         */
  80 
  81 static unsigned char    video_type;             /* Type of display being used   */
  82 static unsigned long    video_mem_base;         /* Base of video memory         */
  83 static unsigned long    video_mem_term;         /* End of video memory          */
  84 static unsigned long    video_size_row;         /* Bytes per row                */
  85 static unsigned char    video_page;             /* Initial video page           */
  86 static unsigned short   video_port_reg;         /* Video register select port   */
  87 static unsigned short   video_port_val;         /* Video register value port    */
  88 static int can_do_color = 0;
  89 static int printable = 0;
  90 
  91 static struct {
  92         unsigned short  vc_video_erase_char;    /* Background erase character */
  93         unsigned char   vc_attr;                /* Current attributes */
  94         unsigned char   vc_def_color;           /* Default colors */
  95         unsigned char   vc_color;               /* Foreground & background */
  96         unsigned char   vc_s_color;             /* Saved foreground & background */
  97         unsigned char   vc_ulcolor;             /* Colour for underline mode */
  98         unsigned char   vc_halfcolor;           /* Colour for half intensity mode */
  99         unsigned long   vc_origin;              /* Used for EGA/VGA fast scroll */
 100         unsigned long   vc_scr_end;             /* Used for EGA/VGA fast scroll */
 101         unsigned long   vc_pos;
 102         unsigned long   vc_x,vc_y;
 103         unsigned long   vc_top,vc_bottom;
 104         unsigned long   vc_state;
 105         unsigned long   vc_npar,vc_par[NPAR];
 106         unsigned long   vc_video_mem_start;     /* Start of video RAM           */
 107         unsigned long   vc_video_mem_end;       /* End of video RAM (sort of)   */
 108         unsigned long   vc_saved_x;
 109         unsigned long   vc_saved_y;
 110         /* mode flags */
 111         unsigned long   vc_charset      : 1;    /* Character set G0 / G1 */
 112         unsigned long   vc_s_charset    : 1;    /* Saved character set */
 113         unsigned long   vc_decscnm      : 1;    /* Screen Mode */
 114         unsigned long   vc_decom        : 1;    /* Origin Mode */
 115         unsigned long   vc_decawm       : 1;    /* Autowrap Mode */
 116         unsigned long   vc_deccm        : 1;    /* Cursor Visible */
 117         unsigned long   vc_decim        : 1;    /* Insert Mode */
 118         /* attribute flags */
 119         unsigned long   vc_intensity    : 2;    /* 0=half-bright, 1=normal, 2=bold */
 120         unsigned long   vc_underline    : 1;
 121         unsigned long   vc_blink        : 1;
 122         unsigned long   vc_reverse      : 1;
 123         unsigned long   vc_s_intensity  : 2;    /* saved rendition */
 124         unsigned long   vc_s_underline  : 1;
 125         unsigned long   vc_s_blink      : 1;
 126         unsigned long   vc_s_reverse    : 1;
 127         /* misc */
 128         unsigned long   vc_ques         : 1;
 129         unsigned long   vc_need_wrap    : 1;
 130         unsigned long   vc_tab_stop[5];         /* Tab stops. 160 columns. */
 131         unsigned char   vc_kbdmode;
 132         unsigned char * vc_translate;
 133         unsigned char * vc_G0_charset;
 134         unsigned char * vc_G1_charset;
 135         unsigned char * vc_saved_G0;
 136         unsigned char * vc_saved_G1;
 137         /* additional information is in vt_kern.h */
 138 } vc_cons [NR_CONSOLES];
 139 
 140 unsigned short *vc_scrbuf[NR_CONSOLES];
 141 static unsigned short * vc_scrmembuf;
 142 static int console_blanked = 0;
 143 
 144 #define origin          (vc_cons[currcons].vc_origin)
 145 #define scr_end         (vc_cons[currcons].vc_scr_end)
 146 #define pos             (vc_cons[currcons].vc_pos)
 147 #define top             (vc_cons[currcons].vc_top)
 148 #define bottom          (vc_cons[currcons].vc_bottom)
 149 #define x               (vc_cons[currcons].vc_x)
 150 #define y               (vc_cons[currcons].vc_y)
 151 #define state           (vc_cons[currcons].vc_state)
 152 #define npar            (vc_cons[currcons].vc_npar)
 153 #define par             (vc_cons[currcons].vc_par)
 154 #define ques            (vc_cons[currcons].vc_ques)
 155 #define attr            (vc_cons[currcons].vc_attr)
 156 #define saved_x         (vc_cons[currcons].vc_saved_x)
 157 #define saved_y         (vc_cons[currcons].vc_saved_y)
 158 #define translate       (vc_cons[currcons].vc_translate)
 159 #define G0_charset      (vc_cons[currcons].vc_G0_charset)
 160 #define G1_charset      (vc_cons[currcons].vc_G1_charset)
 161 #define saved_G0        (vc_cons[currcons].vc_saved_G0)
 162 #define saved_G1        (vc_cons[currcons].vc_saved_G1)
 163 #define video_mem_start (vc_cons[currcons].vc_video_mem_start)
 164 #define video_mem_end   (vc_cons[currcons].vc_video_mem_end)
 165 #define video_erase_char (vc_cons[currcons].vc_video_erase_char)        
 166 #define decscnm         (vc_cons[currcons].vc_decscnm)
 167 #define decom           (vc_cons[currcons].vc_decom)
 168 #define decawm          (vc_cons[currcons].vc_decawm)
 169 #define deccm           (vc_cons[currcons].vc_deccm)
 170 #define decim           (vc_cons[currcons].vc_decim)
 171 #define need_wrap       (vc_cons[currcons].vc_need_wrap)
 172 #define color           (vc_cons[currcons].vc_color)
 173 #define s_color         (vc_cons[currcons].vc_s_color)
 174 #define def_color       (vc_cons[currcons].vc_def_color)
 175 #define foreground      (color & 0x0f)
 176 #define background      (color & 0xf0)
 177 #define charset         (vc_cons[currcons].vc_charset)
 178 #define s_charset       (vc_cons[currcons].vc_s_charset)
 179 #define intensity       (vc_cons[currcons].vc_intensity)
 180 #define underline       (vc_cons[currcons].vc_underline)
 181 #define blink           (vc_cons[currcons].vc_blink)
 182 #define reverse         (vc_cons[currcons].vc_reverse)
 183 #define s_intensity     (vc_cons[currcons].vc_s_intensity)
 184 #define s_underline     (vc_cons[currcons].vc_s_underline)
 185 #define s_blink         (vc_cons[currcons].vc_s_blink)
 186 #define s_reverse       (vc_cons[currcons].vc_s_reverse)
 187 #define ulcolor         (vc_cons[currcons].vc_ulcolor)
 188 #define halfcolor       (vc_cons[currcons].vc_halfcolor)
 189 #define kbdmode         (vc_cons[currcons].vc_kbdmode)
 190 #define tab_stop        (vc_cons[currcons].vc_tab_stop)
 191 #define vcmode          (vt_cons[currcons].vc_mode)
 192 #define vtmode          (vt_cons[currcons].vt_mode)
 193 #define vtpid           (vt_cons[currcons].vt_pid)
 194 #define vtnewvt         (vt_cons[currcons].vt_newvt)
 195 
 196 #define set_kbd(x) set_vc_kbd_flag(kbd_table+currcons,x)
 197 #define clr_kbd(x) clr_vc_kbd_flag(kbd_table+currcons,x)
 198 #define is_kbd(x) vc_kbd_flag(kbd_table+currcons,x)
 199 
 200 #define decarm          VC_REPEAT
 201 #define decckm          VC_CKMODE
 202 #define kbdapplic       VC_APPLIC
 203 #define kbdraw          VC_RAW
 204 #define lnm             VC_CRLF
 205 
 206 int blankinterval = 10*60*HZ;
 207 static int screen_size = 0;
 208 
 209 /*
 210  * this is what the terminal answers to a ESC-Z or csi0c query.
 211  */
 212 #define VT100ID "\033[?1;2c"
 213 #define VT102ID "\033[?6c"
 214 
 215 static unsigned char * translations[] = {
 216 /* 8-bit Latin-1 mapped to the PC charater set: '\0' means non-printable */
 217 (unsigned char *)
 218         "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
 219         "\0\0\0\0\0\0\0\0\0\0\376\0\0\0\0\0"
 220         " !\"#$%&'()*+,-./0123456789:;<=>?"
 221         "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
 222         "`abcdefghijklmnopqrstuvwxyz{|}~\0"
 223         "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
 224         "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
 225         "\377\255\233\234\376\235\174\025\376\376\246\256\252\055\376\376"
 226         "\370\361\375\376\376\346\024\371\376\376\247\257\254\253\376\250"
 227         "\376\376\376\376\216\217\222\200\376\220\376\376\376\376\376\376"
 228         "\376\245\376\376\376\376\231\376\350\376\376\376\232\376\376\341"
 229         "\205\240\203\376\204\206\221\207\212\202\210\211\215\241\214\213"
 230         "\376\244\225\242\223\376\224\366\355\227\243\226\201\376\376\230",
 231 /* vt100 graphics */
 232 (unsigned char *)
 233         "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
 234         "\0\0\0\0\0\0\0\0\0\0\376\0\0\0\0\0"
 235         " !\"#$%&'()*+,-./0123456789:;<=>?"
 236         "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^ "
 237         "\004\261\007\007\007\007\370\361\007\007\331\277\332\300\305\304"
 238         "\304\304\137\137\303\264\301\302\263\363\362\343\330\234\007\0"
 239         "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
 240         "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
 241         "\377\255\233\234\376\235\174\025\376\376\246\256\252\055\376\376"
 242         "\370\361\375\376\376\346\024\371\376\376\247\257\254\253\376\250"
 243         "\376\376\376\376\216\217\222\200\376\220\376\376\376\376\376\376"
 244         "\376\245\376\376\376\376\231\376\376\376\376\376\232\376\376\341"
 245         "\205\240\203\376\204\206\221\207\212\202\210\211\215\241\214\213"
 246         "\376\244\225\242\223\376\224\366\376\227\243\226\201\376\376\230",
 247 /* IBM graphics: minimal translations (BS, CR, LF, LL, SO, SI and ESC) */
 248 (unsigned char *)
 249         "\000\001\002\003\004\005\006\007\000\011\000\013\000\000\000\000"
 250         "\020\021\022\023\024\025\026\027\030\031\032\000\034\035\036\037"
 251         "\040\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057"
 252         "\060\061\062\063\064\065\066\067\070\071\072\073\074\075\076\077"
 253         "\100\101\102\103\104\105\106\107\110\111\112\113\114\115\116\117"
 254         "\120\121\122\123\124\125\126\127\130\131\132\133\134\135\136\137"
 255         "\140\141\142\143\144\145\146\147\150\151\152\153\154\155\156\157"
 256         "\160\161\162\163\164\165\166\167\170\171\172\173\174\175\176\177"
 257         "\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217"
 258         "\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237"
 259         "\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257"
 260         "\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277"
 261         "\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317"
 262         "\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337"
 263         "\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357"
 264         "\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377"
 265 };
 266 
 267 #define NORM_TRANS (translations[0])
 268 #define GRAF_TRANS (translations[1])
 269 #define NULL_TRANS (translations[2])
 270 
 271 static unsigned char color_table[] = { 0, 4, 2, 6, 1, 5, 3, 7,
 272                                        8,12,10,14, 9,13,11,15 };
 273 
 274 /*
 275  * gotoxy() must verify all boundaries, because the arguments
 276  * might also be negative. If the given position is out of
 277  * bounds, the cursor is placed at the nearest margin.
 278  */
 279 static void gotoxy(int currcons, int new_x, int new_y)
     /* [previous][next][first][last][top][bottom][index][help] */
 280 {
 281         int max_y;
 282 
 283         if (new_x < 0)
 284                 x = 0;
 285         else
 286                 if (new_x >= video_num_columns)
 287                         x = video_num_columns - 1;
 288                 else
 289                         x = new_x;
 290         if (decom) {
 291                 new_y += top;
 292                 max_y = bottom;
 293         } else
 294                 max_y = video_num_lines;
 295         if (new_y < 0)
 296                 y = 0;
 297         else
 298                 if (new_y >= max_y)
 299                         y = max_y - 1;
 300                 else
 301                         y = new_y;
 302         pos = origin + y*video_size_row + (x<<1);
 303         need_wrap = 0;
 304 }
 305 
 306 /*
 307  * *Very* limited hardware scrollback support..
 308  */
 309 static unsigned short __real_origin;
 310 static unsigned short __origin;
 311 
 312 static inline void __set_origin(unsigned short offset)
     /* [previous][next][first][last][top][bottom][index][help] */
 313 {
 314         unsigned long flags;
 315 #ifdef CONFIG_SELECTION
 316         clear_selection();
 317 #endif /* CONFIG_SELECTION */
 318         save_flags(flags); cli();
 319         __origin = offset;
 320         outb_p(12, video_port_reg);
 321         outb_p(offset >> 8, video_port_val);
 322         outb_p(13, video_port_reg);
 323         outb_p(offset, video_port_val);
 324         restore_flags(flags);
 325 }
 326 
 327 void scrollback(int lines)
     /* [previous][next][first][last][top][bottom][index][help] */
 328 {
 329         if (!lines)
 330                 lines = video_num_lines/2;
 331         lines *= video_num_columns;
 332         lines = __origin - lines;
 333         if (lines < 0)
 334                 lines = 0;
 335         __set_origin(lines);
 336 }
 337 
 338 void scrollfront(int lines)
     /* [previous][next][first][last][top][bottom][index][help] */
 339 {
 340         if (!lines)
 341                 lines = video_num_lines/2;
 342         lines *= video_num_columns;
 343         lines = __origin + lines;
 344         if (lines > __real_origin)
 345                 lines = __real_origin;
 346         __set_origin(lines);
 347 }
 348 
 349 static void set_origin(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 350 {
 351         if (video_type != VIDEO_TYPE_EGAC && video_type != VIDEO_TYPE_EGAM)
 352                 return;
 353         if (currcons != fg_console || console_blanked || vcmode == KD_GRAPHICS)
 354                 return;
 355         __real_origin = (origin-video_mem_base) >> 1;
 356         __set_origin(__real_origin);
 357 }
 358 
 359 static inline void hide_cursor(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 360 {
 361         outb_p(14, video_port_reg);
 362         outb_p(0xff&((scr_end-video_mem_base)>>9), video_port_val);
 363         outb_p(15, video_port_reg);
 364         outb_p(0xff&((scr_end-video_mem_base)>>1), video_port_val);
 365 }
 366 
 367 static inline void set_cursor(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 368 {
 369         unsigned long flags;
 370 
 371         if (currcons != fg_console || console_blanked || vcmode == KD_GRAPHICS)
 372                 return;
 373         if (__real_origin != __origin)
 374                 set_origin(__real_origin);
 375         save_flags(flags); cli();
 376         if (deccm) {
 377                 outb_p(14, video_port_reg);
 378                 outb_p(0xff&((pos-video_mem_base)>>9), video_port_val);
 379                 outb_p(15, video_port_reg);
 380                 outb_p(0xff&((pos-video_mem_base)>>1), video_port_val);
 381         } else
 382                 hide_cursor(currcons);
 383         restore_flags(flags);
 384 }
 385 
 386 static void scrup(int currcons, unsigned int t, unsigned int b)
     /* [previous][next][first][last][top][bottom][index][help] */
 387 {
 388         int hardscroll = 1;
 389 
 390         if (b > video_num_lines || t >= b)
 391                 return;
 392         if (video_type != VIDEO_TYPE_EGAC && video_type != VIDEO_TYPE_EGAM)
 393                 hardscroll = 0;
 394         else if (t || b != video_num_lines)
 395                 hardscroll = 0;
 396         if (hardscroll) {
 397                 origin += video_size_row;
 398                 pos += video_size_row;
 399                 scr_end += video_size_row;
 400                 if (scr_end > video_mem_end) {
 401                         __asm__("cld\n\t"
 402                                 "rep\n\t"
 403                                 "movsl\n\t"
 404                                 "movl _video_num_columns,%1\n\t"
 405                                 "rep\n\t"
 406                                 "stosw"
 407                                 : /* no output */
 408                                 :"a" (video_erase_char),
 409                                 "c" ((video_num_lines-1)*video_num_columns>>1),
 410                                 "D" (video_mem_start),
 411                                 "S" (origin)
 412                                 :"cx","di","si");
 413                         scr_end -= origin-video_mem_start;
 414                         pos -= origin-video_mem_start;
 415                         origin = video_mem_start;
 416                 } else {
 417                         __asm__("cld\n\t"
 418                                 "rep\n\t"
 419                                 "stosw"
 420                                 : /* no output */
 421                                 :"a" (video_erase_char),
 422                                 "c" (video_num_columns),
 423                                 "D" (scr_end-video_size_row)
 424                                 :"cx","di");
 425                 }
 426                 set_origin(currcons);
 427         } else {
 428                 __asm__("cld\n\t"
 429                         "rep\n\t"
 430                         "movsl\n\t"
 431                         "movl _video_num_columns,%%ecx\n\t"
 432                         "rep\n\t"
 433                         "stosw"
 434                         : /* no output */
 435                         :"a" (video_erase_char),
 436                         "c" ((b-t-1)*video_num_columns>>1),
 437                         "D" (origin+video_size_row*t),
 438                         "S" (origin+video_size_row*(t+1))
 439                         :"cx","di","si");
 440         }
 441 }
 442 
 443 static void scrdown(int currcons, unsigned int t, unsigned int b)
     /* [previous][next][first][last][top][bottom][index][help] */
 444 {
 445         if (b > video_num_lines || t >= b)
 446                 return;
 447         __asm__("std\n\t"
 448                 "rep\n\t"
 449                 "movsl\n\t"
 450                 "addl $2,%%edi\n\t"     /* %edi has been decremented by 4 */
 451                 "movl _video_num_columns,%%ecx\n\t"
 452                 "rep\n\t"
 453                 "stosw\n\t"
 454                 "cld"
 455                 : /* no output */
 456                 :"a" (video_erase_char),
 457                 "c" ((b-t-1)*video_num_columns>>1),
 458                 "D" (origin+video_size_row*b-4),
 459                 "S" (origin+video_size_row*(b-1)-4)
 460                 :"ax","cx","di","si");
 461 }
 462 
 463 static void lf(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 464 {
 465         if (y+1<bottom) {
 466                 y++;
 467                 pos += video_size_row;
 468                 return;
 469         } else 
 470                 scrup(currcons,top,bottom);
 471         need_wrap = 0;
 472 }
 473 
 474 static void ri(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 475 {
 476         if (y>top) {
 477                 y--;
 478                 pos -= video_size_row;
 479                 return;
 480         } else
 481                 scrdown(currcons,top,bottom);
 482         need_wrap = 0;
 483 }
 484 
 485 static inline void cr(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 486 {
 487         pos -= x<<1;
 488         need_wrap = x = 0;
 489 }
 490 
 491 static inline void bs(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 492 {
 493         if (x) {
 494                 pos -= 2;
 495                 x--;
 496                 need_wrap = 0;
 497         }
 498 }
 499 
 500 static inline void del(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 501 {
 502 #if 0
 503         if (x) {
 504                 if (!need_wrap) {    /* this is not the right condition */
 505                         pos -= 2;
 506                         x--;
 507                 }
 508                 *(unsigned short *)pos = video_erase_char;
 509                 need_wrap = 0;
 510         }
 511 #endif
 512 }
 513 
 514 static void csi_J(int currcons, int vpar)
     /* [previous][next][first][last][top][bottom][index][help] */
 515 {
 516         unsigned long count;
 517         unsigned long start;
 518 
 519         switch (vpar) {
 520                 case 0: /* erase from cursor to end of display */
 521                         count = (scr_end-pos)>>1;
 522                         start = pos;
 523                         break;
 524                 case 1: /* erase from start to cursor */
 525                         count = ((pos-origin)>>1)+1;
 526                         start = origin;
 527                         break;
 528                 case 2: /* erase whole display */
 529                         count = video_num_columns * video_num_lines;
 530                         start = origin;
 531                         break;
 532                 default:
 533                         return;
 534         }
 535         __asm__("cld\n\t"
 536                 "rep\n\t"
 537                 "stosw\n\t"
 538                 : /* no output */
 539                 :"c" (count),
 540                 "D" (start),"a" (video_erase_char)
 541                 :"cx","di");
 542         need_wrap = 0;
 543 }
 544 
 545 static void csi_K(int currcons, int vpar)
     /* [previous][next][first][last][top][bottom][index][help] */
 546 {
 547         long count;
 548         long start;
 549 
 550         switch (vpar) {
 551                 case 0: /* erase from cursor to end of line */
 552                         count = video_num_columns-x;
 553                         start = pos;
 554                         break;
 555                 case 1: /* erase from start of line to cursor */
 556                         start = pos - (x<<1);
 557                         count = x+1;
 558                         break;
 559                 case 2: /* erase whole line */
 560                         start = pos - (x<<1);
 561                         count = video_num_columns;
 562                         break;
 563                 default:
 564                         return;
 565         }
 566         __asm__("cld\n\t"
 567                 "rep\n\t"
 568                 "stosw\n\t"
 569                 : /* no output */
 570                 :"c" (count),
 571                 "D" (start),"a" (video_erase_char)
 572                 :"cx","di");
 573         need_wrap = 0;
 574 }
 575 
 576 /*
 577  *  I hope this works. The monochrome part is untested.
 578  */
 579 static void update_attr(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 580 {
 581         attr = color;
 582         if (can_do_color) {
 583                 if (underline)
 584                         attr = (attr & 0xf0) | ulcolor;
 585                 else if (intensity == 0)
 586                         attr = (attr & 0xf0) | halfcolor;
 587         }
 588         if (reverse ^ decscnm)
 589                 attr = (attr & 0x88) | (((attr >> 4) | (attr << 4)) & 0x77);
 590         if (blink)
 591                 attr ^= 0x80;
 592         if (intensity == 2)
 593                 attr ^= 0x08;
 594         if (!can_do_color) {
 595                 if (underline)
 596                         attr = (attr & 0xf8) | 0x01;
 597                 else if (intensity == 0)
 598                         attr = (attr & 0xf0) | 0x08;
 599         }
 600         if (decscnm)
 601                 video_erase_char = ((color & 0x88) | (((color >> 4) |
 602                         (color << 4)) & 0x77) << 8) | ' ';
 603         else
 604                 video_erase_char = (color << 8) | ' ';
 605 }
 606 
 607 static void default_attr(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 608 {
 609         intensity = 1;
 610         underline = 0;
 611         reverse = 0;
 612         blink = 0;
 613         color = def_color;
 614 }
 615 
 616 static void csi_m(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 617 {
 618         int i;
 619 
 620         for (i=0;i<=npar;i++)
 621                 switch (par[i]) {
 622                         case 0: /* all attributes off */
 623                                 default_attr(currcons);
 624                                 break;
 625                         case 1:
 626                                 intensity = 2;
 627                                 break;
 628                         case 2:
 629                                 intensity = 0;
 630                                 break;
 631                         case 4:
 632                                 underline = 1;
 633                                 break;
 634                         case 5:
 635                                 blink = 1;
 636                                 break;
 637                         case 7:
 638                                 reverse = 1;
 639                                 break;
 640                         case 21:
 641                         case 22:
 642                                 intensity = 1;
 643                                 break;
 644                         case 24:
 645                                 underline = 0;
 646                                 break;
 647                         case 25:
 648                                 blink = 0;
 649                                 break;
 650                         case 27:
 651                                 reverse = 0;
 652                                 break;
 653                         case 39:
 654                                 color = (def_color & 0x0f) | background;
 655                                 break;
 656                         case 49:
 657                                 color = (def_color & 0xf0) | foreground;
 658                                 break;
 659                         default:
 660                                 if (par[i] >= 30 && par[i] <= 37)
 661                                         color = color_table[par[i]-30]
 662                                                 | background; 
 663                                 else if (par[i] >= 40 && par[i] <= 47)
 664                                         color = (color_table[par[i]-40]<<4)
 665                                                 | foreground;
 666                                 break;
 667                 }
 668         update_attr(currcons);
 669 }
 670 
 671 static void respond_string(char * p, int currcons, struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 672 {
 673         while (*p) {
 674                 put_tty_queue(*p, &tty->read_q);
 675                 p++;
 676         }
 677         TTY_READ_FLUSH(tty);
 678 }
 679 
 680 static void respond_num(unsigned int n, int currcons, struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 681 {
 682         char buff[3];
 683         int i = 0;
 684 
 685         do {
 686                 buff[i++] = (n%10)+'0';
 687                 n /= 10;
 688         } while(n && i < 3);    /* We'll take no chances */
 689         while (i--) {
 690                 put_tty_queue(buff[i], &tty->read_q);
 691         }
 692         /* caller must flush */
 693 }
 694 
 695 static void cursor_report(int currcons, struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 696 {
 697         put_tty_queue('\033', &tty->read_q);
 698         put_tty_queue('[', &tty->read_q);
 699         respond_num(y + (decom ? top+1 : 1), currcons, tty);
 700         put_tty_queue(';', &tty->read_q);
 701         respond_num(x+1, currcons, tty);
 702         put_tty_queue('R', &tty->read_q);
 703         TTY_READ_FLUSH(tty);
 704 }
 705 
 706 static inline void status_report(int currcons, struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 707 {
 708         respond_string("\033[0n", currcons, tty);       /* Terminal ok */
 709 }
 710 
 711 static inline void respond_ID(int currcons, struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 712 {
 713         respond_string(VT102ID, currcons, tty);
 714 }
 715 
 716 static void invert_screen(int currcons) {
     /* [previous][next][first][last][top][bottom][index][help] */
 717         unsigned char *p;
 718 
 719         if (can_do_color)
 720                 for (p = (unsigned char *)origin+1; p < (unsigned char *)scr_end; p+=2)
 721                         *p = (*p & 0x88) | (((*p >> 4) | (*p << 4)) & 0x77);
 722         else
 723                 for (p = (unsigned char *)origin+1; p < (unsigned char *)scr_end; p+=2)
 724                         *p ^= *p & 0x07 == 1 ? 0x70 : 0x77;
 725 }
 726 
 727 static void set_mode(int currcons, int on_off)
     /* [previous][next][first][last][top][bottom][index][help] */
 728 {
 729         int i;
 730 
 731         for (i=0; i<=npar; i++)
 732                 if (ques) switch(par[i]) {      /* DEC private modes set/reset */
 733                         case 1:                 /* Cursor keys send ^[Ox/^[[x */
 734                                 if (on_off)
 735                                         set_kbd(decckm);
 736                                 else
 737                                         clr_kbd(decckm);
 738                                 break;
 739                         case 3: /* 80/132 mode switch unimplemented */
 740                                 csi_J(currcons,2);
 741                                 gotoxy(currcons,0,0);
 742                                 break;
 743                         case 5:                 /* Inverted screen on/off */
 744                                 if (decscnm != on_off) {
 745                                         decscnm = on_off;
 746                                         invert_screen(currcons);
 747                                         update_attr(currcons);
 748                                 }
 749                                 break;
 750                         case 6:                 /* Origin relative/absolute */
 751                                 decom = on_off;
 752                                 gotoxy(currcons,0,0);
 753                                 break;
 754                         case 7:                 /* Autowrap on/off */
 755                                 decawm = on_off;
 756                                 break;
 757                         case 8:                 /* Autorepeat on/off */
 758                                 if (on_off)
 759                                         set_kbd(decarm);
 760                                 else
 761                                         clr_kbd(decarm);
 762                                 break;
 763                         case 25:                /* Cursor on/off */
 764                                 deccm = on_off;
 765                                 set_cursor(currcons);
 766                                 break;
 767                 } else switch(par[i]) {         /* ANSI modes set/reset */
 768                         case 4:                 /* Insert Mode on/off */
 769                                 decim = on_off;
 770                                 break;
 771                         case 20:                /* Lf, Enter == CrLf/Lf */
 772                                 if (on_off)
 773                                         set_kbd(lnm);
 774                                 else
 775                                         clr_kbd(lnm);
 776                                 break;
 777                 }
 778 }
 779 
 780 static void setterm_command(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 781 {
 782         switch(par[0]) {
 783                 case 1: /* set color for underline mode */
 784                         if (can_do_color && par[1] < 16) {
 785                                 ulcolor = color_table[par[1]];
 786                                 if (underline)
 787                                         update_attr(currcons);
 788                         }
 789                         break;
 790                 case 2: /* set color for half intensity mode */
 791                         if (can_do_color && par[1] < 16) {
 792                                 halfcolor = color_table[par[1]];
 793                                 if (intensity == 0)
 794                                         update_attr(currcons);
 795                         }
 796                         break;
 797                 case 8: /* store colors as defaults */
 798                         def_color = attr;
 799                         default_attr(currcons);
 800                         update_attr(currcons);
 801                         break;
 802                 case 9: /* set blanking interval */
 803                         blankinterval = ((par[1] < 60) ? par[1] : 60) * 60 * HZ;
 804                         break;
 805         }
 806 }
 807 
 808 static void insert_char(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 809 {
 810         unsigned int i = x;
 811         unsigned short tmp, old = video_erase_char;
 812         unsigned short * p = (unsigned short *) pos;
 813 
 814         while (i++ < video_num_columns) {
 815                 tmp = *p;
 816                 *p = old;
 817                 old = tmp;
 818                 p++;
 819         }
 820         need_wrap = 0;
 821 }
 822 
 823 static void insert_line(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 824 {
 825         scrdown(currcons,y,bottom);
 826         need_wrap = 0;
 827 }
 828 
 829 static void delete_char(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 830 {
 831         unsigned int i = x;
 832         unsigned short * p = (unsigned short *) pos;
 833 
 834         while (++i < video_num_columns) {
 835                 *p = *(p+1);
 836                 p++;
 837         }
 838         *p = video_erase_char;
 839         need_wrap = 0;
 840 }
 841 
 842 static void delete_line(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 843 {
 844         scrup(currcons,y,bottom);
 845         need_wrap = 0;
 846 }
 847 
 848 static void csi_at(int currcons, unsigned int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
 849 {
 850         if (nr > video_num_columns)
 851                 nr = video_num_columns;
 852         else if (!nr)
 853                 nr = 1;
 854         while (nr--)
 855                 insert_char(currcons);
 856 }
 857 
 858 static void csi_L(int currcons, unsigned int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
 859 {
 860         if (nr > video_num_lines)
 861                 nr = video_num_lines;
 862         else if (!nr)
 863                 nr = 1;
 864         while (nr--)
 865                 insert_line(currcons);
 866 }
 867 
 868 static void csi_P(int currcons, unsigned int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
 869 {
 870         if (nr > video_num_columns)
 871                 nr = video_num_columns;
 872         else if (!nr)
 873                 nr = 1;
 874         while (nr--)
 875                 delete_char(currcons);
 876 }
 877 
 878 static void csi_M(int currcons, unsigned int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
 879 {
 880         if (nr > video_num_lines)
 881                 nr = video_num_lines;
 882         else if (!nr)
 883                 nr=1;
 884         while (nr--)
 885                 delete_line(currcons);
 886 }
 887 
 888 static void save_cur(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 889 {
 890         saved_x         = x;
 891         saved_y         = y;
 892         s_intensity     = intensity;
 893         s_underline     = underline;
 894         s_blink         = blink;
 895         s_reverse       = reverse;
 896         s_charset       = charset;
 897         s_color         = color;
 898         saved_G0        = G0_charset;
 899         saved_G1        = G1_charset;
 900 }
 901 
 902 static void restore_cur(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 903 {
 904         gotoxy(currcons,saved_x,saved_y);
 905         intensity       = s_intensity;
 906         underline       = s_underline;
 907         blink           = s_blink;
 908         reverse         = s_reverse;
 909         charset         = s_charset;
 910         color           = s_color;
 911         G0_charset      = saved_G0;
 912         G1_charset      = saved_G1;
 913         translate       = charset ? G1_charset : G0_charset;
 914         update_attr(currcons);
 915         need_wrap = 0;
 916 }
 917 
 918 enum { ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey, 
 919         EShash, ESsetG0, ESsetG1, ESignore };
 920 
 921 static void reset_terminal(int currcons, int do_clear)
     /* [previous][next][first][last][top][bottom][index][help] */
 922 {
 923         top             = 0;
 924         bottom          = video_num_lines;
 925         state           = ESnormal;
 926         ques            = 0;
 927         translate       = NORM_TRANS;
 928         G0_charset      = NORM_TRANS;
 929         G1_charset      = GRAF_TRANS;
 930         charset         = 0;
 931         need_wrap       = 0;
 932 
 933         decscnm         = 0;
 934         decom           = 0;
 935         decawm          = 1;
 936         deccm           = 1;
 937         decim           = 0;
 938 
 939         set_kbd(decarm);
 940         clr_kbd(decckm);
 941         clr_kbd(kbdapplic);
 942         clr_kbd(lnm);
 943         kbd_table[currcons].flags =
 944                 (kbd_table[currcons].flags & ~LED_MASK) |
 945                 (kbd_table[currcons].default_flags & LED_MASK);
 946         kbdmode         = 0;
 947         set_leds();
 948 
 949         default_attr(currcons);
 950         update_attr(currcons);
 951 
 952         tab_stop[0]     = 0x01010100;
 953         tab_stop[1]     =
 954         tab_stop[2]     =
 955         tab_stop[3]     =
 956         tab_stop[4]     = 0x01010101;
 957 
 958         if (do_clear) {
 959                 gotoxy(currcons,0,0);
 960                 csi_J(currcons,2);
 961                 save_cur(currcons);
 962         }
 963 }
 964 
 965 void con_write(struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 966 {
 967         int c;
 968         unsigned int currcons;
 969 
 970         wake_up_interruptible(&tty->write_q.proc_list);
 971         currcons = tty->line - 1;
 972         if (currcons >= NR_CONSOLES) {
 973                 printk("con_write: illegal tty (%d)\n", currcons);
 974                 return;
 975         }
 976 #ifdef CONFIG_SELECTION
 977         /* clear the selection as soon as any characters are to be written
 978            out on the console holding the selection. */
 979         if (!EMPTY(&tty->write_q) && currcons == sel_cons)
 980                 clear_selection();
 981 #endif /* CONFIG_SELECTION */
 982         disable_bh(KEYBOARD_BH);
 983         while (!tty->stopped && (c = get_tty_queue(&tty->write_q)) >= 0) {
 984                 if (state == ESnormal && translate[c]) {
 985                         if (need_wrap) {
 986                                 cr(currcons);
 987                                 lf(currcons);
 988                         }
 989                         if (decim)
 990                                 insert_char(currcons);
 991                         c = translate[c];
 992                         *(unsigned short *) pos = (attr << 8) + c;
 993                         if (x == video_num_columns - 1)
 994                                 need_wrap = decawm;
 995                         else {
 996                                 x++;
 997                                 pos+=2;
 998                         }
 999                         continue;
1000                 }
1001 
1002                 /*
1003                  *  Control characters can be used in the _middle_
1004                  *  of an escape sequence.
1005                  */
1006                 switch (c) {
1007                         case 7:
1008                                 kd_mksound(0x637, HZ/8);
1009                                 continue;
1010                         case 8:
1011                                 bs(currcons);
1012                                 continue;
1013                         case 9:
1014                                 pos -= (x << 1);
1015                                 while (x < video_num_columns - 1) {
1016                                         x++;
1017                                         if (tab_stop[x >> 5] & (1 << (x & 31)))
1018                                                 break;
1019                                 }
1020                                 pos += (x << 1);
1021                                 continue;
1022                         case 10: case 11: case 12:
1023                                 lf(currcons);
1024                                 if (!is_kbd(lnm))
1025                                         continue;
1026                         case 13:
1027                                 cr(currcons);
1028                                 continue;
1029                         case 14:
1030                                 charset = 1;
1031                                 translate = G1_charset;
1032                                 continue;
1033                         case 15:
1034                                 charset = 0;
1035                                 translate = G0_charset;
1036                                 continue;
1037                         case 24: case 26:
1038                                 state = ESnormal;
1039                                 continue;
1040                         case 27:
1041                                 state = ESesc;
1042                                 continue;
1043                         case 127:
1044                                 del(currcons);
1045                                 continue;
1046                         case 128+27:
1047                                 state = ESsquare;
1048                                 continue;
1049                 }
1050                 switch(state) {
1051                         case ESesc:
1052                                 state = ESnormal;
1053                                 switch (c) {
1054                                   case '[':
1055                                         state = ESsquare;
1056                                         continue;
1057                                   case 'E':
1058                                         cr(currcons);
1059                                         lf(currcons);
1060                                         continue;
1061                                   case 'M':
1062                                         ri(currcons);
1063                                         continue;
1064                                   case 'D':
1065                                         lf(currcons);
1066                                         continue;
1067                                   case 'H':
1068                                         tab_stop[x >> 5] |= (1 << (x & 31));
1069                                         continue;
1070                                   case 'Z':
1071                                         respond_ID(currcons,tty);
1072                                         continue;
1073                                   case '7':
1074                                         save_cur(currcons);
1075                                         continue;
1076                                   case '8':
1077                                         restore_cur(currcons);
1078                                         continue;
1079                                   case '(':
1080                                         state = ESsetG0;
1081                                         continue;
1082                                   case ')':
1083                                         state = ESsetG1;
1084                                         continue;
1085                                   case '#':
1086                                         state = EShash;
1087                                         continue;
1088                                   case 'c':
1089                                         reset_terminal(currcons,1);
1090                                         continue;
1091                                   case '>':  /* Numeric keypad */
1092                                         clr_kbd(kbdapplic);
1093                                         continue;
1094                                   case '=':  /* Appl. keypad */
1095                                         set_kbd(kbdapplic);
1096                                         continue;
1097                                 }       
1098                                 continue;
1099                         case ESsquare:
1100                                 for(npar = 0 ; npar < NPAR ; npar++)
1101                                         par[npar] = 0;
1102                                 npar = 0;
1103                                 state = ESgetpars;
1104                                 if (c == '[') { /* Function key */
1105                                         state=ESfunckey;
1106                                         continue;
1107                                 }
1108                                 ques = (c=='?');
1109                                 if (ques)
1110                                         continue;
1111                         case ESgetpars:
1112                                 if (c==';' && npar<NPAR-1) {
1113                                         npar++;
1114                                         continue;
1115                                 } else if (c>='0' && c<='9') {
1116                                         par[npar] *= 10;
1117                                         par[npar] += c-'0';
1118                                         continue;
1119                                 } else state=ESgotpars;
1120                         case ESgotpars:
1121                                 state = ESnormal;
1122                                 switch(c) {
1123                                         case 'h':
1124                                                 set_mode(currcons,1);
1125                                                 continue;
1126                                         case 'l':
1127                                                 set_mode(currcons,0);
1128                                                 continue;
1129                                         case 'n':
1130                                                 if (!ques)
1131                                                         if (par[0] == 5)
1132                                                                 status_report(currcons,tty);
1133                                                         else if (par[0] == 6)
1134                                                                 cursor_report(currcons,tty);
1135                                                 continue;
1136                                 }
1137                                 if (ques) {
1138                                         ques = 0;
1139                                         continue;
1140                                 }
1141                                 switch(c) {
1142                                         case 'G': case '`':
1143                                                 if (par[0]) par[0]--;
1144                                                 gotoxy(currcons,par[0],y);
1145                                                 continue;
1146                                         case 'A':
1147                                                 if (!par[0]) par[0]++;
1148                                                 gotoxy(currcons,x,y-par[0]);
1149                                                 continue;
1150                                         case 'B': case 'e':
1151                                                 if (!par[0]) par[0]++;
1152                                                 gotoxy(currcons,x,y+par[0]);
1153                                                 continue;
1154                                         case 'C': case 'a':
1155                                                 if (!par[0]) par[0]++;
1156                                                 gotoxy(currcons,x+par[0],y);
1157                                                 continue;
1158                                         case 'D':
1159                                                 if (!par[0]) par[0]++;
1160                                                 gotoxy(currcons,x-par[0],y);
1161                                                 continue;
1162                                         case 'E':
1163                                                 if (!par[0]) par[0]++;
1164                                                 gotoxy(currcons,0,y+par[0]);
1165                                                 continue;
1166                                         case 'F':
1167                                                 if (!par[0]) par[0]++;
1168                                                 gotoxy(currcons,0,y-par[0]);
1169                                                 continue;
1170                                         case 'd':
1171                                                 if (par[0]) par[0]--;
1172                                                 gotoxy(currcons,x,par[0]);
1173                                                 continue;
1174                                         case 'H': case 'f':
1175                                                 if (par[0]) par[0]--;
1176                                                 if (par[1]) par[1]--;
1177                                                 gotoxy(currcons,par[1],par[0]);
1178                                                 continue;
1179                                         case 'J':
1180                                                 csi_J(currcons,par[0]);
1181                                                 continue;
1182                                         case 'K':
1183                                                 csi_K(currcons,par[0]);
1184                                                 continue;
1185                                         case 'L':
1186                                                 csi_L(currcons,par[0]);
1187                                                 continue;
1188                                         case 'M':
1189                                                 csi_M(currcons,par[0]);
1190                                                 continue;
1191                                         case 'P':
1192                                                 csi_P(currcons,par[0]);
1193                                                 continue;
1194                                         case 'c':
1195                                                 if (!par[0])
1196                                                         respond_ID(currcons,tty);
1197                                                 continue;
1198                                         case 'g':
1199                                                 if (!par[0])
1200                                                         tab_stop[x >> 5] &= ~(1 << (x & 31));
1201                                                 else if (par[0] == 3) {
1202                                                         tab_stop[0] =
1203                                                         tab_stop[1] =
1204                                                         tab_stop[2] =
1205                                                         tab_stop[3] =
1206                                                         tab_stop[4] = 0;
1207                                                 }
1208                                                 continue;
1209                                         case 'm':
1210                                                 csi_m(currcons);
1211                                                 continue;
1212                                         case 'r':
1213                                                 if (!par[0])
1214                                                         par[0]++;
1215                                                 if (!par[1])
1216                                                         par[1] = video_num_lines;
1217                                                 /* Minimum allowed region is 2 lines */
1218                                                 if (par[0] < par[1] &&
1219                                                     par[1] <= video_num_lines) {
1220                                                         top=par[0]-1;
1221                                                         bottom=par[1];
1222                                                         gotoxy(currcons,0,0);
1223                                                 }
1224                                                 continue;
1225                                         case 's':
1226                                                 save_cur(currcons);
1227                                                 continue;
1228                                         case 'u':
1229                                                 restore_cur(currcons);
1230                                                 continue;
1231                                         case '@':
1232                                                 csi_at(currcons,par[0]);
1233                                                 continue;
1234                                         case ']': /* setterm functions */
1235                                                 setterm_command(currcons);
1236                                                 continue;
1237                                 }
1238                                 continue;
1239                         case ESfunckey:
1240                                 state = ESnormal;
1241                                 continue;
1242                         case EShash:
1243                                 state = ESnormal;
1244                                 if (c == '8') {
1245                                         /* DEC screen alignment test. kludge :-) */
1246                                         video_erase_char =
1247                                                 (video_erase_char & 0xff00) | 'E';
1248                                         csi_J(currcons, 2);
1249                                         video_erase_char =
1250                                                 (video_erase_char & 0xff00) | ' ';
1251                                 }
1252                                 continue;
1253                         case ESsetG0:
1254                                 if (c == '0')
1255                                         G0_charset = GRAF_TRANS;
1256                                 else if (c == 'B')
1257                                         G0_charset = NORM_TRANS;
1258                                 else if (c == 'U')
1259                                         G0_charset = NULL_TRANS;
1260                                 if (charset == 0)
1261                                         translate = G0_charset;
1262                                 state = ESnormal;
1263                                 continue;
1264                         case ESsetG1:
1265                                 if (c == '0')
1266                                         G1_charset = GRAF_TRANS;
1267                                 else if (c == 'B')
1268                                         G1_charset = NORM_TRANS;
1269                                 else if (c == 'U')
1270                                         G1_charset = NULL_TRANS;
1271                                 if (charset == 1)
1272                                         translate = G1_charset;
1273                                 state = ESnormal;
1274                                 continue;
1275                         default:
1276                                 state = ESnormal;
1277                 }
1278         }
1279         if (vcmode != KD_GRAPHICS)
1280                 set_cursor(currcons);
1281         enable_bh(KEYBOARD_BH);
1282 }
1283 
1284 void do_keyboard_interrupt(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1285 {
1286         TTY_READ_FLUSH(TTY_TABLE(0));
1287         timer_active &= ~(1<<BLANK_TIMER);
1288         if (vt_cons[fg_console].vc_mode == KD_GRAPHICS)
1289                 return;
1290         if (console_blanked) {
1291                 timer_table[BLANK_TIMER].expires = 0;
1292                 timer_active |= 1<<BLANK_TIMER;
1293         } else if (blankinterval) {
1294                 timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
1295                 timer_active |= 1<<BLANK_TIMER;
1296         }
1297 }
1298 
1299 void * memsetw(void * s,unsigned short c,int count)
     /* [previous][next][first][last][top][bottom][index][help] */
1300 {
1301 __asm__("cld\n\t"
1302         "rep\n\t"
1303         "stosw"
1304         : /* no output */
1305         :"a" (c),"D" (s),"c" (count)
1306         :"cx","di");
1307 return s;
1308 }
1309 
1310 void console_print(const char * b)
     /* [previous][next][first][last][top][bottom][index][help] */
1311 {
1312         int currcons = fg_console;
1313         unsigned char c;
1314 
1315         if (!printable || currcons<0 || currcons>=NR_CONSOLES)
1316                 return;
1317         while ((c = *(b++)) != 0) {
1318                 if (c == 10 || c == 13 || need_wrap) {
1319                         if (c != 13)
1320                                 lf(currcons);
1321                         cr(currcons);
1322                         if (c == 10 || c == 13)
1323                                 continue;
1324                 }
1325                 *(unsigned short *) pos = (attr << 8) + c;
1326                 if (x == video_num_columns - 1) {
1327                         need_wrap = 1;
1328                         continue;
1329                 }
1330                 x++;
1331                 pos+=2;
1332         }
1333         set_cursor(currcons);
1334         if (vt_cons[fg_console].vc_mode == KD_GRAPHICS)
1335                 return;
1336         timer_active &= ~(1<<BLANK_TIMER);
1337         if (console_blanked) {
1338                 timer_table[BLANK_TIMER].expires = 0;
1339                 timer_active |= 1<<BLANK_TIMER;
1340         } else if (blankinterval) {
1341                 timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
1342                 timer_active |= 1<<BLANK_TIMER;
1343         }
1344 }
1345 
1346 /*
1347  *  long con_init(long);
1348  *
1349  * This routine initalizes console interrupts, and does nothing
1350  * else. If you want the screen to clear, call tty_write with
1351  * the appropriate escape-sequece.
1352  *
1353  * Reads the information preserved by setup.s to determine the current display
1354  * type and sets everything accordingly.
1355  */
1356 long con_init(long kmem_start)
     /* [previous][next][first][last][top][bottom][index][help] */
1357 {
1358         char *display_desc = "????";
1359         int currcons = 0;
1360         long base;
1361         int orig_x = ORIG_X;
1362         int orig_y = ORIG_Y;
1363 
1364         vc_scrmembuf = (unsigned short *) kmem_start;
1365         video_num_columns = ORIG_VIDEO_COLS;
1366         video_size_row = video_num_columns * 2;
1367         video_num_lines = ORIG_VIDEO_LINES;
1368         video_page = ORIG_VIDEO_PAGE;
1369         screen_size = (video_num_lines * video_size_row);
1370         kmem_start += NR_CONSOLES * screen_size;
1371         timer_table[BLANK_TIMER].fn = blank_screen;
1372         timer_table[BLANK_TIMER].expires = 0;
1373         if (blankinterval) {
1374                 timer_table[BLANK_TIMER].expires = jiffies+blankinterval;
1375                 timer_active |= 1<<BLANK_TIMER;
1376         }
1377         
1378         if (ORIG_VIDEO_MODE == 7)       /* Is this a monochrome display? */
1379         {
1380                 video_mem_base = 0xb0000;
1381                 video_port_reg = 0x3b4;
1382                 video_port_val = 0x3b5;
1383                 if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
1384                 {
1385                         video_type = VIDEO_TYPE_EGAM;
1386                         video_mem_term = 0xb8000;
1387                         display_desc = "EGA+";
1388                 }
1389                 else
1390                 {
1391                         video_type = VIDEO_TYPE_MDA;
1392                         video_mem_term = 0xb2000;
1393                         display_desc = "*MDA";
1394                 }
1395         }
1396         else                            /* If not, it is color. */
1397         {
1398                 can_do_color = 1;
1399                 video_mem_base = 0xb8000;
1400                 video_port_reg  = 0x3d4;
1401                 video_port_val  = 0x3d5;
1402                 if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
1403                 {
1404                         video_type = VIDEO_TYPE_EGAC;
1405                         video_mem_term = 0xc0000;
1406                         display_desc = "EGA+";
1407                 }
1408                 else
1409                 {
1410                         video_type = VIDEO_TYPE_CGA;
1411                         video_mem_term = 0xba000;
1412                         display_desc = "*CGA";
1413                 }
1414         }
1415         
1416         /* Initialize the variables used for scrolling (mostly EGA/VGA) */
1417 
1418         base = (long)vc_scrmembuf;
1419         for (currcons = 0; currcons<NR_CONSOLES; currcons++) {
1420                 pos = origin = video_mem_start = base;
1421                 scr_end = video_mem_end = (base += screen_size);
1422                 vc_scrbuf[currcons] = (unsigned short *) origin;
1423                 vcmode          = KD_TEXT;
1424                 vtmode.mode     = VT_AUTO;
1425                 vtmode.waitv    = 0;
1426                 vtmode.relsig   = 0;
1427                 vtmode.acqsig   = 0;
1428                 vtmode.frsig    = 0;
1429                 vtpid           = -1;
1430                 vtnewvt         = -1;
1431                 clr_kbd(kbdraw);
1432                 def_color       = 0x07;   /* white */
1433                 ulcolor         = 0x0f;   /* bold white */
1434                 halfcolor       = 0x08;   /* grey */
1435                 reset_terminal(currcons, currcons);
1436         }
1437         currcons = fg_console = 0;
1438 
1439         video_mem_start = video_mem_base;
1440         video_mem_end = video_mem_term;
1441         origin = video_mem_start;
1442         scr_end = video_mem_start + video_num_lines * video_size_row;
1443         gotoxy(currcons,0,0);
1444         save_cur(currcons);
1445         gotoxy(currcons,orig_x,orig_y);
1446         update_screen(fg_console);
1447         printable = 1;
1448         printk("Console: %s %s %ldx%ld, %d virtual consoles\n",
1449                 can_do_color?"colour":"mono",
1450                 display_desc,
1451                 video_num_columns,video_num_lines,
1452                 NR_CONSOLES);
1453         register_console(console_print);
1454         return kmem_start;
1455 }
1456 
1457 /*
1458  * kbdsave doesn't need to do anything: it's all handled automatically
1459  * with the new data structures..
1460  */
1461 void kbdsave(int new_console)
     /* [previous][next][first][last][top][bottom][index][help] */
1462 {
1463 }
1464 
1465 static void get_scrmem(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
1466 {
1467         memcpy((void *)vc_scrbuf[currcons],(void *)origin, screen_size);
1468         video_mem_start = (unsigned long)vc_scrbuf[currcons];
1469         origin  = video_mem_start;
1470         scr_end = video_mem_end = video_mem_start+screen_size;
1471         pos = origin + y*video_size_row + (x<<1);
1472 }
1473 
1474 static void set_scrmem(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
1475 {
1476 #ifdef CONFIG_HGA
1477   /* This works with XFree86 1.2, 1.3 and 2.0
1478      This code could be extended and made more generally useful if we could
1479      determine the actual video mode. It appears that this should be
1480      possible on a genuine Hercules card, but I (WM) haven't been able to
1481      read from any of the required registers on my clone card.
1482      */
1483         /* This code should work with Hercules and MDA cards. */
1484         if (video_type == VIDEO_TYPE_MDA)
1485           {
1486             if (vcmode == KD_TEXT)
1487               {
1488                 /* Ensure that the card is in text mode. */
1489                 int     i;
1490                 static char herc_txt_tbl[12] = {
1491                   0x61,0x50,0x52,0x0f,0x19,6,0x19,0x19,2,0x0d,0x0b,0x0c };
1492                 outb_p(0, 0x3bf);  /* Back to power-on defaults */
1493                 outb_p(0, 0x3b8);  /* Blank the screen, select page 0, etc */
1494                 for ( i = 0 ; i < 12 ; i++ )
1495                   {
1496                     outb_p(i, 0x3b4);
1497                     outb_p(herc_txt_tbl[i], 0x3b5);
1498                   }
1499               }
1500 #define HGA_BLINKER_ON 0x20
1501 #define HGA_SCREEN_ON  8
1502             /* Make sure that the hardware is not blanked */
1503             outb_p(HGA_BLINKER_ON | HGA_SCREEN_ON, 0x3b8);
1504           }
1505 #endif CONFIG_HGA
1506 
1507         video_mem_start = video_mem_base;
1508         video_mem_end = video_mem_term;
1509         origin  = video_mem_start;
1510         scr_end = video_mem_start + screen_size;
1511         pos = origin + y*video_size_row + (x<<1);
1512         memcpy((void *)video_mem_base, (void *)vc_scrbuf[fg_console], screen_size);
1513 }
1514 
1515 void blank_screen(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1516 {
1517         if (console_blanked)
1518                 return;
1519         timer_table[BLANK_TIMER].fn = unblank_screen;
1520         get_scrmem(fg_console);
1521         hide_cursor(fg_console);
1522         console_blanked = 1;
1523         memsetw((void *)video_mem_base, 0x0020, video_mem_term-video_mem_base );
1524 }
1525 
1526 void unblank_screen(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1527 {
1528         if (!console_blanked)
1529                 return;
1530         timer_table[BLANK_TIMER].fn = blank_screen;
1531         if (blankinterval) {
1532                 timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
1533                 timer_active |= 1<<BLANK_TIMER;
1534         }
1535         console_blanked = 0;
1536         set_scrmem(fg_console);
1537         set_origin(fg_console);
1538         set_cursor(fg_console);
1539 }
1540 
1541 void update_screen(int new_console)
     /* [previous][next][first][last][top][bottom][index][help] */
1542 {
1543         static int lock = 0;
1544 
1545         if (new_console == fg_console || lock)
1546                 return;
1547         lock = 1;
1548         kbdsave(new_console);
1549         get_scrmem(fg_console); 
1550         fg_console = new_console;
1551         set_scrmem(fg_console); 
1552         set_origin(fg_console);
1553         set_cursor(new_console);
1554         set_leds();
1555         compute_shiftstate();
1556         lock = 0;
1557 }
1558 
1559 int do_screendump(int arg)
     /* [previous][next][first][last][top][bottom][index][help] */
1560 {
1561         char *sptr, *buf = (char *)arg;
1562         int currcons, l;
1563 
1564         if (!suser())
1565                 return -EPERM;
1566         l = verify_area(VERIFY_WRITE, buf,2+video_num_columns*video_num_lines);
1567         if (l)
1568                 return l;
1569         currcons = get_fs_byte(buf+1);
1570         if ((currcons<0) || (currcons>NR_CONSOLES))
1571                 return -EIO;
1572         put_fs_byte((char)(video_num_lines),buf++);     
1573         put_fs_byte((char)(video_num_columns),buf++);
1574         currcons = (currcons ? currcons-1 : fg_console);
1575         sptr = (char *) origin;
1576         for (l=video_num_lines*video_num_columns; l>0 ; l--, sptr++)
1577                 put_fs_byte(*sptr++,buf++);     
1578         return(0);
1579 }
1580 
1581 /*
1582  * All we do is set the write and ioctl subroutines; later on maybe we'll
1583  * dynamically allocate the console screen memory.
1584  */
1585 int con_open(struct tty_struct *tty, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
1586 {
1587         tty->write = con_write;
1588         tty->ioctl = vt_ioctl;
1589         if (tty->line > NR_CONSOLES)
1590                 return -ENODEV;
1591         return 0;
1592 }
1593 
1594 #ifdef CONFIG_SELECTION
1595 /* correction factor for when screen is hardware-scrolled */
1596 #define hwscroll_offset (currcons == fg_console ? ((__real_origin - __origin) << 1) : 0)
1597 
1598 /* set reverse video on characters s-e of console with selection. */
1599 static void highlight(const int currcons, const int s, const int e)
     /* [previous][next][first][last][top][bottom][index][help] */
1600 {
1601         unsigned char *p, *p1, *p2;
1602 
1603         p1 = (unsigned char *)origin - hwscroll_offset + s + 1;
1604         p2 = (unsigned char *)origin - hwscroll_offset + e + 1;
1605         if (p1 > p2)
1606         {
1607                 p = p1;
1608                 p1 = p2;
1609                 p2 = p;
1610         }
1611         for (p = p1; p <= p2; p += 2)
1612                 *p = (*p & 0x88) | ((*p << 4) & 0x70) | ((*p >> 4) & 0x07);
1613 }
1614 
1615 /* is c in range [a-zA-Z0-9_]? */
1616 static inline int inword(const char c) { return (isalnum(c) || c == '_'); }
     /* [previous][next][first][last][top][bottom][index][help] */
1617 
1618 /* does screen address p correspond to character at LH/RH edge of screen? */
1619 static inline int atedge(const int p)
     /* [previous][next][first][last][top][bottom][index][help] */
1620 {
1621         return (!(p % video_size_row) || !((p + 2) % video_size_row));
1622 }
1623 
1624 /* constrain v such that l <= v <= u */
1625 static inline short limit(const int v, const int l, const int u)
     /* [previous][next][first][last][top][bottom][index][help] */
1626 {
1627         return (v < l) ? l : ((v > u) ? u : v);
1628 }
1629 
1630 /* set the current selection. Invoked by ioctl(). */
1631 int set_selection(const int arg)
     /* [previous][next][first][last][top][bottom][index][help] */
1632 {
1633         unsigned short *args, xs, ys, xe, ye;
1634         int currcons = fg_console;
1635         int sel_mode, new_sel_start, new_sel_end, spc;
1636         char *bp, *obp, *spos;
1637         int i, ps, pe;
1638         char *off = (char *)origin - hwscroll_offset;
1639 
1640         unblank_screen();
1641         args = (unsigned short *)(arg + 1);
1642         xs = get_fs_word(args++) - 1;
1643         ys = get_fs_word(args++) - 1;
1644         xe = get_fs_word(args++) - 1;
1645         ye = get_fs_word(args++) - 1;
1646         sel_mode = get_fs_word(args);
1647 
1648         xs = limit(xs, 0, video_num_columns - 1);
1649         ys = limit(ys, 0, video_num_lines - 1);
1650         xe = limit(xe, 0, video_num_columns - 1);
1651         ye = limit(ye, 0, video_num_lines - 1);
1652         ps = ys * video_size_row + (xs << 1);
1653         pe = ye * video_size_row + (xe << 1);
1654 
1655         if (ps > pe)    /* make sel_start <= sel_end */
1656         {
1657                 int tmp = ps;
1658                 ps = pe;
1659                 pe = tmp;
1660         }
1661 
1662         switch (sel_mode)
1663         {
1664                 case 0: /* character-by-character selection */
1665                 default:
1666                         new_sel_start = ps;
1667                         new_sel_end = pe;
1668                         break;
1669                 case 1: /* word-by-word selection */
1670                         spc = isspace(*(off + ps));
1671                         for (new_sel_start = ps; ; ps -= 2)
1672                         {
1673                                 if ((spc && !isspace(*(off + ps))) ||
1674                                     (!spc && !inword(*(off + ps))))
1675                                         break;
1676                                 new_sel_start = ps;
1677                                 if (!(ps % video_size_row))
1678                                         break;
1679                         }
1680                         spc = isspace(*(off + pe));
1681                         for (new_sel_end = pe; ; pe += 2)
1682                         {
1683                                 if ((spc && !isspace(*(off + pe))) ||
1684                                     (!spc && !inword(*(off + pe))))
1685                                         break;
1686                                 new_sel_end = pe;
1687                                 if (!((pe + 2) % video_size_row))
1688                                         break;
1689                         }
1690                         break;
1691                 case 2: /* line-by-line selection */
1692                         new_sel_start = ps - ps % video_size_row;
1693                         new_sel_end = pe + video_size_row
1694                                     - pe % video_size_row - 2;
1695                         break;
1696         }
1697         /* select to end of line if on trailing space */
1698         if (new_sel_end > new_sel_start &&
1699                 !atedge(new_sel_end) && isspace(*(off + new_sel_end)))
1700         {
1701                 for (pe = new_sel_end + 2; ; pe += 2)
1702                 {
1703                         if (!isspace(*(off + pe)) || atedge(pe))
1704                                 break;
1705                 }
1706                 if (isspace(*(off + pe)))
1707                         new_sel_end = pe;
1708         }
1709         if (sel_cons != currcons)
1710         {
1711                 clear_selection();
1712                 sel_cons = currcons;
1713         }
1714         if (sel_start == -1)    /* no current selection */
1715                 highlight(sel_cons, new_sel_start, new_sel_end);
1716         else if (new_sel_start == sel_start)
1717         {
1718                 if (new_sel_end == sel_end)     /* no action required */
1719                         return 0;
1720                 else if (new_sel_end > sel_end) /* extend to right */
1721                         highlight(sel_cons, sel_end + 2, new_sel_end);
1722                 else                            /* contract from right */
1723                         highlight(sel_cons, new_sel_end + 2, sel_end);
1724         }
1725         else if (new_sel_end == sel_end)
1726         {
1727                 if (new_sel_start < sel_start)  /* extend to left */
1728                         highlight(sel_cons, new_sel_start, sel_start - 2);
1729                 else                            /* contract from left */
1730                         highlight(sel_cons, sel_start, new_sel_start - 2);
1731         }
1732         else    /* some other case; start selection from scratch */
1733         {
1734                 clear_selection();
1735                 highlight(sel_cons, new_sel_start, new_sel_end);
1736         }
1737         sel_start = new_sel_start;
1738         sel_end = new_sel_end;
1739         obp = bp = sel_buffer;
1740         for (i = sel_start; i <= sel_end; i += 2)
1741         {
1742                 spos = (char *)off + i;
1743                 *bp++ = *spos;
1744                 if (!isspace(*spos))
1745                         obp = bp;
1746                 if (! ((i + 2) % video_size_row))
1747                 {
1748                         /* strip trailing blanks from line and add newline,
1749                            unless non-space at end of line. */
1750                         if (obp != bp)
1751                         {
1752                                 bp = obp;
1753                                 *bp++ = '\r';
1754                         }
1755                         obp = bp;
1756                 }
1757                 /* check for space, leaving room for next character, possible
1758                    newline, and null at end. */
1759                 if (bp - sel_buffer > SEL_BUFFER_SIZE - 3)
1760                         break;
1761         }
1762         *bp = '\0';
1763         return 0;
1764 }
1765 
1766 /* insert the contents of the selection buffer into the queue of the
1767    tty associated with the current console. Invoked by ioctl(). */
1768 int paste_selection(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
1769 {
1770         char *bp = sel_buffer;
1771 
1772         if (! *bp)
1773                 return 0;
1774         unblank_screen();
1775         while (*bp)
1776         {
1777                 put_tty_queue(*bp, &tty->read_q);
1778                 bp++;
1779         }
1780         TTY_READ_FLUSH(tty);
1781         return 0;
1782 }
1783 
1784 /* remove the current selection highlight, if any, from the console holding
1785    the selection. */
1786 static void clear_selection()
     /* [previous][next][first][last][top][bottom][index][help] */
1787 {
1788         if (sel_start != -1)
1789         {
1790                 highlight(sel_cons, sel_start, sel_end);
1791                 sel_start = -1;
1792         }
1793 }
1794 #endif /* CONFIG_SELECTION */

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