root/drivers/char/console.c

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

DEFINITIONS

This source file includes following definitions.
  1. gotoxy
  2. __set_origin
  3. scrollback
  4. scrollfront
  5. set_origin
  6. hide_cursor
  7. set_cursor
  8. scrup
  9. scrdown
  10. lf
  11. ri
  12. cr
  13. bs
  14. del
  15. csi_J
  16. csi_K
  17. update_attr
  18. default_attr
  19. csi_m
  20. respond_string
  21. cursor_report
  22. status_report
  23. respond_ID
  24. invert_screen
  25. set_mode
  26. setterm_command
  27. insert_char
  28. insert_line
  29. delete_char
  30. delete_line
  31. csi_at
  32. csi_L
  33. csi_P
  34. csi_M
  35. save_cur
  36. restore_cur
  37. reset_terminal
  38. con_stop
  39. con_start
  40. con_write
  41. con_write_room
  42. con_chars_in_buffer
  43. poke_blanked_console
  44. memsetw
  45. console_print
  46. con_throttle
  47. con_unthrottle
  48. con_init
  49. kbdsave
  50. get_scrmem
  51. set_scrmem
  52. blank_screen
  53. unblank_screen
  54. update_screen
  55. do_screendump
  56. con_open
  57. highlight
  58. inword
  59. atedge
  60. limit
  61. set_selection
  62. paste_selection
  63. clear_selection
  64. set_get_font
  65. con_set_font
  66. con_get_font
  67. con_set_trans
  68. con_get_trans

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

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