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

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