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

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