root/drivers/char/console.c

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

DEFINITIONS

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

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

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