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         if (y+1<bottom) {
 745                 y++;
 746                 pos += video_size_row;
 747                 return;
 748         } else 
 749                 scrup(currcons,top,bottom);
 750         need_wrap = 0;
 751 }
 752 
 753 static void ri(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 754 {
 755         if (y>top) {
 756                 y--;
 757                 pos -= video_size_row;
 758                 return;
 759         } else
 760                 scrdown(currcons,top,bottom);
 761         need_wrap = 0;
 762 }
 763 
 764 static inline void cr(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 765 {
 766         pos -= x<<1;
 767         need_wrap = x = 0;
 768 }
 769 
 770 static inline void bs(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 771 {
 772         if (x) {
 773                 pos -= 2;
 774                 x--;
 775                 need_wrap = 0;
 776         }
 777 }
 778 
 779 static inline void del(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 780 {
 781         /* ignored */
 782 }
 783 
 784 static void csi_J(int currcons, int vpar)
     /* [previous][next][first][last][top][bottom][index][help] */
 785 {
 786         unsigned long count;
 787         unsigned long start;
 788 
 789         switch (vpar) {
 790                 case 0: /* erase from cursor to end of display */
 791                         count = (scr_end-pos)>>1;
 792                         start = pos;
 793                         break;
 794                 case 1: /* erase from start to cursor */
 795                         count = ((pos-origin)>>1)+1;
 796                         start = origin;
 797                         break;
 798                 case 2: /* erase whole display */
 799                         count = video_num_columns * video_num_lines;
 800                         start = origin;
 801                         break;
 802                 default:
 803                         return;
 804         }
 805         __asm__("cld\n\t"
 806                 "rep\n\t"
 807                 "stosw\n\t"
 808                 : /* no output */
 809                 :"c" (count),
 810                 "D" (start),"a" (video_erase_char)
 811                 :"cx","di");
 812         need_wrap = 0;
 813 }
 814 
 815 static void csi_K(int currcons, int vpar)
     /* [previous][next][first][last][top][bottom][index][help] */
 816 {
 817         long count;
 818         long start;
 819 
 820         switch (vpar) {
 821                 case 0: /* erase from cursor to end of line */
 822                         count = video_num_columns-x;
 823                         start = pos;
 824                         break;
 825                 case 1: /* erase from start of line to cursor */
 826                         start = pos - (x<<1);
 827                         count = x+1;
 828                         break;
 829                 case 2: /* erase whole line */
 830                         start = pos - (x<<1);
 831                         count = video_num_columns;
 832                         break;
 833                 default:
 834                         return;
 835         }
 836         __asm__("cld\n\t"
 837                 "rep\n\t"
 838                 "stosw\n\t"
 839                 : /* no output */
 840                 :"c" (count),
 841                 "D" (start),"a" (video_erase_char)
 842                 :"cx","di");
 843         need_wrap = 0;
 844 }
 845 
 846 static void csi_X(int currcons, int vpar) /* erase the following vpar positions */
     /* [previous][next][first][last][top][bottom][index][help] */
 847 {                                         /* not vt100? */
 848         long count;
 849         long start;
 850 
 851         if (!vpar)
 852                 vpar++;
 853 
 854         start=pos;
 855         count=(vpar > video_num_columns-x) ? (video_num_columns-x) : vpar;
 856 
 857         __asm__("cld\n\t"
 858                 "rep\n\t"
 859                 "stosw\n\t"
 860                 : /* no output */
 861                 :"c" (count),
 862                 "D" (start),"a" (video_erase_char)
 863                 :"cx","di");
 864         need_wrap = 0;
 865 }
 866 
 867 static void update_attr(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 868 {
 869         attr = color;
 870         if (can_do_color) {
 871                 if (underline)
 872                         attr = (attr & 0xf0) | ulcolor;
 873                 else if (intensity == 0)
 874                         attr = (attr & 0xf0) | halfcolor;
 875         }
 876         if (reverse ^ decscnm)
 877                 attr = (attr & 0x88) | (((attr >> 4) | (attr << 4)) & 0x77);
 878         if (blink)
 879                 attr ^= 0x80;
 880         if (intensity == 2)
 881                 attr ^= 0x08;
 882         if (!can_do_color) {
 883                 if (underline)
 884                         attr = (attr & 0xf8) | 0x01;
 885                 else if (intensity == 0)
 886                         attr = (attr & 0xf0) | 0x08;
 887         }
 888         if (decscnm)
 889                 video_erase_char = (((color & 0x88) | (((color >> 4) | (color << 4)) & 0x77)) << 8) | ' ';
 890         else
 891                 video_erase_char = (color << 8) | ' ';
 892 }
 893 
 894 static void default_attr(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 895 {
 896         intensity = 1;
 897         underline = 0;
 898         reverse = 0;
 899         blink = 0;
 900         color = def_color;
 901 }
 902 
 903 static void csi_m(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 904 {
 905         int i;
 906 
 907         for (i=0;i<=npar;i++)
 908                 switch (par[i]) {
 909                         case 0: /* all attributes off */
 910                                 default_attr(currcons);
 911                                 break;
 912                         case 1:
 913                                 intensity = 2;
 914                                 break;
 915                         case 2:
 916                                 intensity = 0;
 917                                 break;
 918                         case 4:
 919                                 underline = 1;
 920                                 break;
 921                         case 5:
 922                                 blink = 1;
 923                                 break;
 924                         case 7:
 925                                 reverse = 1;
 926                                 break;
 927                         case 10: /* ANSI X3.64-1979 (SCO-ish?)
 928                                   * Select primary font, don't display
 929                                   * control chars if defined, don't set
 930                                   * bit 8 on output.
 931                                   */
 932                                 translate = (charset == 0
 933                                                 ? G0_charset
 934                                                 : G1_charset);
 935                                 disp_ctrl = 0;
 936                                 toggle_meta = 0;
 937                                 break;
 938                         case 11: /* ANSI X3.64-1979 (SCO-ish?)
 939                                   * Select first alternate font, let's
 940                                   * chars < 32 be displayed as ROM chars.
 941                                   */
 942                                 translate = NULL_TRANS;
 943                                 disp_ctrl = 1;
 944                                 toggle_meta = 0;
 945                                 break;
 946                         case 12: /* ANSI X3.64-1979 (SCO-ish?)
 947                                   * Select second alternate font, toggle
 948                                   * high bit before displaying as ROM char.
 949                                   */
 950                                 translate = NULL_TRANS;
 951                                 disp_ctrl = 1;
 952                                 toggle_meta = 1;
 953                                 break;
 954                         case 21:
 955                         case 22:
 956                                 intensity = 1;
 957                                 break;
 958                         case 24:
 959                                 underline = 0;
 960                                 break;
 961                         case 25:
 962                                 blink = 0;
 963                                 break;
 964                         case 27:
 965                                 reverse = 0;
 966                                 break;
 967                         case 38: /* ANSI X3.64-1979 (SCO-ish?)
 968                                   * Enables underscore, white foreground
 969                                   * with white underscore (Linux - use
 970                                   * default foreground).
 971                                   */
 972                                 color = (def_color & 0x0f) | background;
 973                                 underline = 1;
 974                                 break;
 975                         case 39: /* ANSI X3.64-1979 (SCO-ish?)
 976                                   * Disable underline option.
 977                                   * Reset colour to default? It did this
 978                                   * before...
 979                                   */
 980                                 color = (def_color & 0x0f) | background;
 981                                 underline = 0;
 982                                 break;
 983                         case 49:
 984                                 color = (def_color & 0xf0) | foreground;
 985                                 break;
 986                         default:
 987                                 if (par[i] >= 30 && par[i] <= 37)
 988                                         color = color_table[par[i]-30]
 989                                                 | background; 
 990                                 else if (par[i] >= 40 && par[i] <= 47)
 991                                         color = (color_table[par[i]-40]<<4)
 992                                                 | foreground;
 993                                 break;
 994                 }
 995         update_attr(currcons);
 996 }
 997 
 998 static void respond_string(char * p, struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 999 {
1000         while (*p) {
1001                 tty_insert_flip_char(tty, *p, 0);
1002                 p++;
1003         }
1004         tty_schedule_flip(tty);
1005 }
1006 
1007 static void cursor_report(int currcons, struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
1008 {
1009         char buf[40];
1010 
1011         sprintf(buf, "\033[%ld;%ldR", y + (decom ? top+1 : 1), x+1);
1012         respond_string(buf, tty);
1013 }
1014 
1015 #ifdef CONFIG_SELECTION
1016 static void mouse_report(int currcons, struct tty_struct * tty,
     /* [previous][next][first][last][top][bottom][index][help] */
1017                          int butt, int mrx, int mry)
1018 {
1019         char buf[8];
1020 
1021         sprintf(buf, "\033[M%c%c%c", (char)(' ' + butt), (char)('!' + mrx),
1022                 (char)('!' + mry));
1023         respond_string(buf, tty);
1024 }
1025 #endif
1026 
1027 static inline void status_report(int currcons, struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
1028 {
1029         respond_string("\033[0n", tty); /* Terminal ok */
1030 }
1031 
1032 static inline void respond_ID(int currcons, struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
1033 {
1034         respond_string(VT102ID, tty);
1035 }
1036 
1037 static void invert_screen(int currcons) {
     /* [previous][next][first][last][top][bottom][index][help] */
1038         unsigned char *p;
1039 
1040         if (can_do_color)
1041                 for (p = (unsigned char *)origin+1; p < (unsigned char *)scr_end; p+=2)
1042                         *p = (*p & 0x88) | (((*p >> 4) | (*p << 4)) & 0x77);
1043         else
1044                 for (p = (unsigned char *)origin+1; p < (unsigned char *)scr_end; p+=2)
1045                         *p ^= *p & 0x07 == 1 ? 0x70 : 0x77;
1046 }
1047 
1048 static void set_mode(int currcons, int on_off)
     /* [previous][next][first][last][top][bottom][index][help] */
1049 {
1050         int i;
1051 
1052         for (i=0; i<=npar; i++)
1053                 if (ques) switch(par[i]) {      /* DEC private modes set/reset */
1054                         case 1:                 /* Cursor keys send ^[Ox/^[[x */
1055                                 if (on_off)
1056                                         set_kbd(decckm);
1057                                 else
1058                                         clr_kbd(decckm);
1059                                 break;
1060                         case 3: /* 80/132 mode switch unimplemented */
1061                                 deccolm = on_off;
1062 #if 0
1063                                 (void) vc_resize(video_num_lines, deccolm ? 132 : 80);
1064                                 /* this alone does not suffice; some user mode
1065                                    utility has to change the hardware regs */
1066 #endif
1067                                 break;
1068                         case 5:                 /* Inverted screen on/off */
1069                                 if (decscnm != on_off) {
1070                                         decscnm = on_off;
1071                                         invert_screen(currcons);
1072                                         update_attr(currcons);
1073                                 }
1074                                 break;
1075                         case 6:                 /* Origin relative/absolute */
1076                                 decom = on_off;
1077                                 gotoxy(currcons,0,0);
1078                                 break;
1079                         case 7:                 /* Autowrap on/off */
1080                                 decawm = on_off;
1081                                 break;
1082                         case 8:                 /* Autorepeat on/off */
1083                                 if (on_off)
1084                                         set_kbd(decarm);
1085                                 else
1086                                         clr_kbd(decarm);
1087                                 break;
1088                         case 9:
1089                                 report_mouse = on_off ? 1 : 0;
1090                                 break;
1091                         case 25:                /* Cursor on/off */
1092                                 deccm = on_off;
1093                                 set_cursor(currcons);
1094                                 break;
1095                         case 1000:
1096                                 report_mouse = on_off ? 2 : 0;
1097                                 break;
1098                 } else switch(par[i]) {         /* ANSI modes set/reset */
1099                         case 4:                 /* Insert Mode on/off */
1100                                 decim = on_off;
1101                                 break;
1102                         case 20:                /* Lf, Enter == CrLf/Lf */
1103                                 if (on_off)
1104                                         set_kbd(lnm);
1105                                 else
1106                                         clr_kbd(lnm);
1107                                 break;
1108                 }
1109 }
1110 
1111 static void setterm_command(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
1112 {
1113         switch(par[0]) {
1114                 case 1: /* set color for underline mode */
1115                         if (can_do_color && par[1] < 16) {
1116                                 ulcolor = color_table[par[1]];
1117                                 if (underline)
1118                                         update_attr(currcons);
1119                         }
1120                         break;
1121                 case 2: /* set color for half intensity mode */
1122                         if (can_do_color && par[1] < 16) {
1123                                 halfcolor = color_table[par[1]];
1124                                 if (intensity == 0)
1125                                         update_attr(currcons);
1126                         }
1127                         break;
1128                 case 8: /* store colors as defaults */
1129                         def_color = attr;
1130                         default_attr(currcons);
1131                         update_attr(currcons);
1132                         break;
1133                 case 9: /* set blanking interval */
1134                         blankinterval = ((par[1] < 60) ? par[1] : 60) * 60 * HZ;
1135                         break;
1136         }
1137 }
1138 
1139 static void insert_char(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
1140 {
1141         unsigned int i = x;
1142         unsigned short tmp, old = video_erase_char;
1143         unsigned short * p = (unsigned short *) pos;
1144 
1145         while (i++ < video_num_columns) {
1146                 tmp = *p;
1147                 *p = old;
1148                 old = tmp;
1149                 p++;
1150         }
1151         need_wrap = 0;
1152 }
1153 
1154 static void insert_line(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
1155 {
1156         scrdown(currcons,y,bottom);
1157         need_wrap = 0;
1158 }
1159 
1160 static void delete_char(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
1161 {
1162         unsigned int i = x;
1163         unsigned short * p = (unsigned short *) pos;
1164 
1165         while (++i < video_num_columns) {
1166                 *p = *(p+1);
1167                 p++;
1168         }
1169         *p = video_erase_char;
1170         need_wrap = 0;
1171 }
1172 
1173 static void delete_line(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
1174 {
1175         scrup(currcons,y,bottom);
1176         need_wrap = 0;
1177 }
1178 
1179 static void csi_at(int currcons, unsigned int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
1180 {
1181         if (nr > video_num_columns)
1182                 nr = video_num_columns;
1183         else if (!nr)
1184                 nr = 1;
1185         while (nr--)
1186                 insert_char(currcons);
1187 }
1188 
1189 static void csi_L(int currcons, unsigned int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
1190 {
1191         if (nr > video_num_lines)
1192                 nr = video_num_lines;
1193         else if (!nr)
1194                 nr = 1;
1195         while (nr--)
1196                 insert_line(currcons);
1197 }
1198 
1199 static void csi_P(int currcons, unsigned int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
1200 {
1201         if (nr > video_num_columns)
1202                 nr = video_num_columns;
1203         else if (!nr)
1204                 nr = 1;
1205         while (nr--)
1206                 delete_char(currcons);
1207 }
1208 
1209 static void csi_M(int currcons, unsigned int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
1210 {
1211         if (nr > video_num_lines)
1212                 nr = video_num_lines;
1213         else if (!nr)
1214                 nr=1;
1215         while (nr--)
1216                 delete_line(currcons);
1217 }
1218 
1219 static void save_cur(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
1220 {
1221         saved_x         = x;
1222         saved_y         = y;
1223         s_intensity     = intensity;
1224         s_underline     = underline;
1225         s_blink         = blink;
1226         s_reverse       = reverse;
1227         s_charset       = charset;
1228         s_color         = color;
1229         saved_G0        = G0_charset;
1230         saved_G1        = G1_charset;
1231 }
1232 
1233 static void restore_cur(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
1234 {
1235         gotoxy(currcons,saved_x,saved_y);
1236         intensity       = s_intensity;
1237         underline       = s_underline;
1238         blink           = s_blink;
1239         reverse         = s_reverse;
1240         charset         = s_charset;
1241         color           = s_color;
1242         G0_charset      = saved_G0;
1243         G1_charset      = saved_G1;
1244         translate       = charset ? G1_charset : G0_charset;
1245         update_attr(currcons);
1246         need_wrap = 0;
1247 }
1248 
1249 enum { ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey, 
1250         EShash, ESsetG0, ESsetG1, ESpercent, ESignore };
1251 
1252 static void reset_terminal(int currcons, int do_clear)
     /* [previous][next][first][last][top][bottom][index][help] */
1253 {
1254         top             = 0;
1255         bottom          = video_num_lines;
1256         vc_state        = ESnormal;
1257         ques            = 0;
1258         translate       = NORM_TRANS;
1259         G0_charset      = NORM_TRANS;
1260         G1_charset      = GRAF_TRANS;
1261         charset         = 0;
1262         need_wrap       = 0;
1263         report_mouse    = 0;
1264         utf             = 0;
1265         utf_count       = 0;
1266 
1267         disp_ctrl       = 0;
1268         toggle_meta     = 0;
1269 
1270         decscnm         = 0;
1271         decom           = 0;
1272         decawm          = 1;
1273         deccm           = 1;
1274         decim           = 0;
1275 
1276         set_kbd(decarm);
1277         clr_kbd(decckm);
1278         clr_kbd(kbdapplic);
1279         clr_kbd(lnm);
1280         kbd_table[currcons].lockstate = 0;
1281         kbd_table[currcons].ledmode = LED_SHOW_FLAGS;
1282         kbd_table[currcons].ledflagstate = kbd_table[currcons].default_ledflagstate;
1283         set_leds();
1284 
1285         default_attr(currcons);
1286         update_attr(currcons);
1287 
1288         tab_stop[0]     = 0x01010100;
1289         tab_stop[1]     =
1290         tab_stop[2]     =
1291         tab_stop[3]     =
1292         tab_stop[4]     = 0x01010101;
1293 
1294         gotoxy(currcons,0,0);
1295         save_cur(currcons);
1296         if (do_clear)
1297             csi_J(currcons,2);
1298 }
1299 
1300 /*
1301  * Turn the Scroll-Lock LED on when the tty is stopped
1302  */
1303 static void con_stop(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
1304 {
1305         int console_num;
1306         if (!tty)
1307                 return;
1308         console_num = MINOR(tty->device) - (tty->driver.minor_start);
1309         if (!vc_cons_allocated(console_num))
1310                 return;
1311         set_vc_kbd_led(kbd_table + console_num, VC_SCROLLOCK);
1312         set_leds();
1313 }
1314 
1315 /*
1316  * Turn the Scroll-Lock LED off when the console is started
1317  */
1318 static void con_start(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
1319 {
1320         int console_num;
1321         if (!tty)
1322                 return;
1323         console_num = MINOR(tty->device) - (tty->driver.minor_start);
1324         if (!vc_cons_allocated(console_num))
1325                 return;
1326         clr_vc_kbd_led(kbd_table + console_num, VC_SCROLLOCK);
1327         set_leds();
1328 }
1329 
1330 static int con_write(struct tty_struct * tty, int from_user,
     /* [previous][next][first][last][top][bottom][index][help] */
1331                      unsigned char *buf, int count)
1332 {
1333         int c, tc, ok, n = 0;
1334         unsigned int currcons;
1335         struct vt_struct *vt = (struct vt_struct *)tty->driver_data;
1336 
1337         currcons = vt->vc_num;
1338         if (!vc_cons_allocated(currcons)) {
1339             /* could this happen? */
1340             static int error = 0;
1341             if (!error) {
1342                 error = 1;
1343                 printk("con_write: tty %d not allocated\n", currcons+1);
1344             }
1345             return 0;
1346         }
1347 #ifdef CONFIG_SELECTION
1348         /* clear the selection */
1349         if (currcons == sel_cons)
1350                 clear_selection();
1351 #endif /* CONFIG_SELECTION */
1352         disable_bh(KEYBOARD_BH);
1353         while (!tty->stopped && count) {
1354                 c = from_user ? get_fs_byte(buf) : *buf;
1355                 buf++; n++; count--;
1356 
1357                 if (utf) {
1358                     /* Combine UTF-8 into Unicode */
1359                     /* Incomplete characters silently ignored */
1360                     if(c > 0x7f) {   
1361                         /* UTF-8 to Latin-1 decoding */
1362                         if (utf_count > 0 && (c & 0xc0) == 0x80) {
1363                                 utf_char = (utf_char << 6) | (c & 0x3f);
1364                                 utf_count--;
1365                                 if (utf_count == 0)
1366                                     c = utf_char;
1367                                 else continue;
1368                         } else {
1369                                 if ((c & 0xe0) == 0xc0) {
1370                                     utf_count = 1;
1371                                     utf_char = (c & 0x1f);
1372                                 } else if ((c & 0xf0) == 0xe0) {
1373                                     utf_count = 2;
1374                                     utf_char = (c & 0x0f);
1375                                 } else
1376                                     utf_count = 0;
1377                                 continue;
1378                         }
1379                     } else
1380                         utf_count = 0;
1381 
1382                     /* Now try to find out how to display it */
1383                     if (c > 0xff) {
1384                         tc = conv_uni_to_pc(c);
1385                         if (tc == -2)
1386                           continue;
1387                         vc_state = ESnormal;
1388                         if (tc == -1)
1389                           tc = 0376;    /* small square: symbol not found */
1390                         ok = 1;
1391                     } else {
1392                         tc = NORM_TRANS[c];
1393                         ok = 0;
1394                     }
1395                 } else {        /* no utf */
1396                     tc = translate[toggle_meta ? (c|0x80) : c];
1397                     ok = 0;
1398                 }
1399 
1400                 /* Can print ibm (even if 0), and latin1 provided
1401                    it is a printing char or control chars are printed ^@ */
1402                 if (!ok && tc && (c >= 32 || (disp_ctrl && (c&0x7f) != 27)))
1403                     ok = 1;
1404 
1405                 if (vc_state == ESnormal && ok) {
1406                         if (need_wrap) {
1407                                 cr(currcons);
1408                                 lf(currcons);
1409                         }
1410                         if (decim)
1411                                 insert_char(currcons);
1412                         *(unsigned short *) pos = (attr << 8) + tc;
1413                         if (x == video_num_columns - 1)
1414                                 need_wrap = decawm;
1415                         else {
1416                                 x++;
1417                                 pos+=2;
1418                         }
1419                         continue;
1420                 }
1421 
1422                 /*
1423                  *  Control characters can be used in the _middle_
1424                  *  of an escape sequence.
1425                  */
1426                 switch (c) {
1427                         case 7:
1428                                 kd_mksound(0x637, HZ/8);
1429                                 continue;
1430                         case 8:
1431                                 bs(currcons);
1432                                 continue;
1433                         case 9:
1434                                 pos -= (x << 1);
1435                                 while (x < video_num_columns - 1) {
1436                                         x++;
1437                                         if (tab_stop[x >> 5] & (1 << (x & 31)))
1438                                                 break;
1439                                 }
1440                                 pos += (x << 1);
1441                                 continue;
1442                         case 10: case 11: case 12:
1443                                 lf(currcons);
1444                                 if (!is_kbd(lnm))
1445                                         continue;
1446                         case 13:
1447                                 cr(currcons);
1448                                 continue;
1449                         case 14:
1450                                 charset = 1;
1451                                 translate = G1_charset;
1452                                 continue;
1453                         case 15:
1454                                 charset = 0;
1455                                 translate = G0_charset;
1456                                 continue;
1457                         case 24: case 26:
1458                                 vc_state = ESnormal;
1459                                 continue;
1460                         case 27:
1461                                 vc_state = ESesc;
1462                                 continue;
1463                         case 127:
1464                                 del(currcons);
1465                                 continue;
1466                         case 128+27:
1467                                 vc_state = ESsquare;
1468                                 continue;
1469                 }
1470                 switch(vc_state) {
1471                         case ESesc:
1472                                 vc_state = ESnormal;
1473                                 switch (c) {
1474                                   case '[':
1475                                         vc_state = ESsquare;
1476                                         continue;
1477                                   case '%':
1478                                         vc_state = ESpercent;
1479                                         continue;
1480                                   case 'E':
1481                                         cr(currcons);
1482                                         lf(currcons);
1483                                         continue;
1484                                   case 'M':
1485                                         ri(currcons);
1486                                         continue;
1487                                   case 'D':
1488                                         lf(currcons);
1489                                         continue;
1490                                   case 'H':
1491                                         tab_stop[x >> 5] |= (1 << (x & 31));
1492                                         continue;
1493                                   case 'Z':
1494                                         respond_ID(currcons,tty);
1495                                         continue;
1496                                   case '7':
1497                                         save_cur(currcons);
1498                                         continue;
1499                                   case '8':
1500                                         restore_cur(currcons);
1501                                         continue;
1502                                   case '(':
1503                                         vc_state = ESsetG0;
1504                                         continue;
1505                                   case ')':
1506                                         vc_state = ESsetG1;
1507                                         continue;
1508                                   case '#':
1509                                         vc_state = EShash;
1510                                         continue;
1511                                   case 'c':
1512                                         reset_terminal(currcons,1);
1513                                         continue;
1514                                   case '>':  /* Numeric keypad */
1515                                         clr_kbd(kbdapplic);
1516                                         continue;
1517                                   case '=':  /* Appl. keypad */
1518                                         set_kbd(kbdapplic);
1519                                         continue;
1520                                 }       
1521                                 continue;
1522                         case ESsquare:
1523                                 for(npar = 0 ; npar < NPAR ; npar++)
1524                                         par[npar] = 0;
1525                                 npar = 0;
1526                                 vc_state = ESgetpars;
1527                                 if (c == '[') { /* Function key */
1528                                         vc_state=ESfunckey;
1529                                         continue;
1530                                 }
1531                                 ques = (c=='?');
1532                                 if (ques)
1533                                         continue;
1534                         case ESgetpars:
1535                                 if (c==';' && npar<NPAR-1) {
1536                                         npar++;
1537                                         continue;
1538                                 } else if (c>='0' && c<='9') {
1539                                         par[npar] *= 10;
1540                                         par[npar] += c-'0';
1541                                         continue;
1542                                 } else vc_state=ESgotpars;
1543                         case ESgotpars:
1544                                 vc_state = ESnormal;
1545                                 switch(c) {
1546                                         case 'h':
1547                                                 set_mode(currcons,1);
1548                                                 continue;
1549                                         case 'l':
1550                                                 set_mode(currcons,0);
1551                                                 continue;
1552                                         case 'n':
1553                                                 if (!ques)
1554                                                         if (par[0] == 5)
1555                                                                 status_report(currcons,tty);
1556                                                         else if (par[0] == 6)
1557                                                                 cursor_report(currcons,tty);
1558                                                 continue;
1559                                 }
1560                                 if (ques) {
1561                                         ques = 0;
1562                                         continue;
1563                                 }
1564                                 switch(c) {
1565                                         case 'G': case '`':
1566                                                 if (par[0]) par[0]--;
1567                                                 gotoxy(currcons,par[0],y);
1568                                                 continue;
1569                                         case 'A':
1570                                                 if (!par[0]) par[0]++;
1571                                                 gotoxy(currcons,x,y-par[0]);
1572                                                 continue;
1573                                         case 'B': case 'e':
1574                                                 if (!par[0]) par[0]++;
1575                                                 gotoxy(currcons,x,y+par[0]);
1576                                                 continue;
1577                                         case 'C': case 'a':
1578                                                 if (!par[0]) par[0]++;
1579                                                 gotoxy(currcons,x+par[0],y);
1580                                                 continue;
1581                                         case 'D':
1582                                                 if (!par[0]) par[0]++;
1583                                                 gotoxy(currcons,x-par[0],y);
1584                                                 continue;
1585                                         case 'E':
1586                                                 if (!par[0]) par[0]++;
1587                                                 gotoxy(currcons,0,y+par[0]);
1588                                                 continue;
1589                                         case 'F':
1590                                                 if (!par[0]) par[0]++;
1591                                                 gotoxy(currcons,0,y-par[0]);
1592                                                 continue;
1593                                         case 'd':
1594                                                 if (par[0]) par[0]--;
1595                                                 gotoxy(currcons,x,par[0]);
1596                                                 continue;
1597                                         case 'H': case 'f':
1598                                                 if (par[0]) par[0]--;
1599                                                 if (par[1]) par[1]--;
1600                                                 gotoxy(currcons,par[1],par[0]);
1601                                                 continue;
1602                                         case 'J':
1603                                                 csi_J(currcons,par[0]);
1604                                                 continue;
1605                                         case 'K':
1606                                                 csi_K(currcons,par[0]);
1607                                                 continue;
1608                                         case 'L':
1609                                                 csi_L(currcons,par[0]);
1610                                                 continue;
1611                                         case 'M':
1612                                                 csi_M(currcons,par[0]);
1613                                                 continue;
1614                                         case 'P':
1615                                                 csi_P(currcons,par[0]);
1616                                                 continue;
1617                                         case 'c':
1618                                                 if (!par[0])
1619                                                         respond_ID(currcons,tty);
1620                                                 continue;
1621                                         case 'g':
1622                                                 if (!par[0])
1623                                                         tab_stop[x >> 5] &= ~(1 << (x & 31));
1624                                                 else if (par[0] == 3) {
1625                                                         tab_stop[0] =
1626                                                         tab_stop[1] =
1627                                                         tab_stop[2] =
1628                                                         tab_stop[3] =
1629                                                         tab_stop[4] = 0;
1630                                                 }
1631                                                 continue;
1632                                         case 'm':
1633                                                 csi_m(currcons);
1634                                                 continue;
1635                                         case 'q': /* DECLL - but only 3 leds */
1636                                                 /* map 0,1,2,3 to 0,1,2,4 */
1637                                                 if (par[0] < 4)
1638                                                   setledstate(kbd_table + currcons,
1639                                                               (par[0] < 3) ? par[0] : 4);
1640                                                 continue;
1641                                         case 'r':
1642                                                 if (!par[0])
1643                                                         par[0]++;
1644                                                 if (!par[1])
1645                                                         par[1] = video_num_lines;
1646                                                 /* Minimum allowed region is 2 lines */
1647                                                 if (par[0] < par[1] &&
1648                                                     par[1] <= video_num_lines) {
1649                                                         top=par[0]-1;
1650                                                         bottom=par[1];
1651                                                         gotoxy(currcons,0,0);
1652                                                 }
1653                                                 continue;
1654                                         case 's':
1655                                                 save_cur(currcons);
1656                                                 continue;
1657                                         case 'u':
1658                                                 restore_cur(currcons);
1659                                                 continue;
1660                                         case 'X':
1661                                                 csi_X(currcons, par[0]);
1662                                                 continue;
1663                                         case '@':
1664                                                 csi_at(currcons,par[0]);
1665                                                 continue;
1666                                         case ']': /* setterm functions */
1667                                                 setterm_command(currcons);
1668                                                 continue;
1669                                 }
1670                                 continue;
1671                         case ESpercent:
1672                                 vc_state = ESnormal;
1673                                 switch (c) {
1674                                   case '@':  /* defined in ISO 2022 */
1675                                         utf = 0;
1676                                         continue;
1677                                   case '8':
1678                                         /* ISO/ECMA hasn't yet registered an
1679                                            official ESC sequence for UTF-8,
1680                                            so this one (ESC %8) will likely
1681                                            change in the future. */
1682                                         utf = 1;
1683                                         continue;
1684                                 }
1685                                 continue;
1686                         case ESfunckey:
1687                                 vc_state = ESnormal;
1688                                 continue;
1689                         case EShash:
1690                                 vc_state = ESnormal;
1691                                 if (c == '8') {
1692                                         /* DEC screen alignment test. kludge :-) */
1693                                         video_erase_char =
1694                                                 (video_erase_char & 0xff00) | 'E';
1695                                         csi_J(currcons, 2);
1696                                         video_erase_char =
1697                                                 (video_erase_char & 0xff00) | ' ';
1698                                 }
1699                                 continue;
1700                         case ESsetG0:
1701                                 if (c == '0')
1702                                         G0_charset = GRAF_TRANS;
1703                                 else if (c == 'B')
1704                                         G0_charset = NORM_TRANS;
1705                                 else if (c == 'U')
1706                                         G0_charset = NULL_TRANS;
1707                                 else if (c == 'K')
1708                                         G0_charset = USER_TRANS;
1709                                 if (charset == 0)
1710                                         translate = G0_charset;
1711                                 vc_state = ESnormal;
1712                                 continue;
1713                         case ESsetG1:
1714                                 if (c == '0')
1715                                         G1_charset = GRAF_TRANS;
1716                                 else if (c == 'B')
1717                                         G1_charset = NORM_TRANS;
1718                                 else if (c == 'U')
1719                                         G1_charset = NULL_TRANS;
1720                                 else if (c == 'K')
1721                                         G1_charset = USER_TRANS;
1722                                 if (charset == 1)
1723                                         translate = G1_charset;
1724                                 vc_state = ESnormal;
1725                                 continue;
1726                         default:
1727                                 vc_state = ESnormal;
1728                 }
1729         }
1730         if (vcmode != KD_GRAPHICS)
1731                 set_cursor(currcons);
1732         enable_bh(KEYBOARD_BH);
1733         return n;
1734 }
1735 
1736 static int con_write_room(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
1737 {
1738         if (tty->stopped)
1739                 return 0;
1740         return 4096;            /* No limit, really; we're not buffering */
1741 }
1742 
1743 static int con_chars_in_buffer(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
1744 {
1745         return 0;               /* we're not buffering */
1746 }
1747 
1748 void poke_blanked_console(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1749 {
1750         timer_active &= ~(1<<BLANK_TIMER);
1751         if (vt_cons[fg_console]->vc_mode == KD_GRAPHICS)
1752                 return;
1753         if (console_blanked) {
1754                 timer_table[BLANK_TIMER].expires = 0;
1755                 timer_active |= 1<<BLANK_TIMER;
1756         } else if (blankinterval) {
1757                 timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
1758                 timer_active |= 1<<BLANK_TIMER;
1759         }
1760 }
1761 
1762 void console_print(const char * b)
     /* [previous][next][first][last][top][bottom][index][help] */
1763 {
1764         int currcons = fg_console;
1765         unsigned char c;
1766 
1767         if (!printable)
1768                 return;  /* console not yet initialized */
1769 
1770         if (!vc_cons_allocated(currcons)) {
1771                 /* impossible */
1772                 printk("console_print: tty %d not allocated ??\n", currcons+1);
1773                 return;
1774         }
1775 
1776         while ((c = *(b++)) != 0) {
1777                 if (c == 10 || c == 13 || need_wrap) {
1778                         if (c != 13)
1779                                 lf(currcons);
1780                         cr(currcons);
1781                         if (c == 10 || c == 13)
1782                                 continue;
1783                 }
1784                 *(unsigned short *) pos = (attr << 8) + c;
1785                 if (x == video_num_columns - 1) {
1786                         need_wrap = 1;
1787                         continue;
1788                 }
1789                 x++;
1790                 pos+=2;
1791         }
1792         set_cursor(currcons);
1793         if (vt_cons[fg_console]->vc_mode == KD_GRAPHICS)
1794                 return;
1795         timer_active &= ~(1<<BLANK_TIMER);
1796         if (console_blanked) {
1797                 timer_table[BLANK_TIMER].expires = 0;
1798                 timer_active |= 1<<BLANK_TIMER;
1799         } else if (blankinterval) {
1800                 timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
1801                 timer_active |= 1<<BLANK_TIMER;
1802         }
1803 }
1804 
1805 /*
1806  * con_throttle and con_unthrottle are only used for
1807  * paste_selection(), which has to stuff in a large number of
1808  * characters...
1809  */
1810 static void con_throttle(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
1811 {
1812 }
1813 
1814 static void con_unthrottle(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
1815 {
1816         struct vt_struct *vt = (struct vt_struct *) tty->driver_data;
1817 
1818         wake_up_interruptible(&vt->paste_wait);
1819 }
1820 
1821 static void vc_init(unsigned int currcons, unsigned long rows, unsigned long cols, int do_clear)
     /* [previous][next][first][last][top][bottom][index][help] */
1822 {
1823         long base = (long) vc_scrbuf[currcons];
1824 
1825         video_num_columns = cols;
1826         video_num_lines = rows;
1827         video_size_row = cols<<1;
1828         video_screen_size = video_num_lines * video_size_row;
1829 
1830         pos = origin = video_mem_start = base;
1831         scr_end = base + video_screen_size;
1832         video_mem_end = base + video_screen_size;
1833         reset_vc(currcons);
1834         def_color       = 0x07;   /* white */
1835         ulcolor         = 0x0f;   /* bold white */
1836         halfcolor       = 0x08;   /* grey */
1837         vt_cons[currcons]->paste_wait = 0;
1838         reset_terminal(currcons, do_clear);
1839 }
1840 
1841 static void con_setsize(unsigned long rows, unsigned long cols)
     /* [previous][next][first][last][top][bottom][index][help] */
1842 {
1843         video_num_lines = rows;
1844         video_num_columns = cols;
1845         video_size_row = 2 * cols;
1846         video_screen_size = video_num_lines * video_size_row;
1847 }
1848 
1849 /*
1850  *  long con_init(long);
1851  *
1852  * This routine initializes console interrupts, and does nothing
1853  * else. If you want the screen to clear, call tty_write with
1854  * the appropriate escape-sequence.
1855  *
1856  * Reads the information preserved by setup.s to determine the current display
1857  * type and sets everything accordingly.
1858  */
1859 long con_init(long kmem_start)
     /* [previous][next][first][last][top][bottom][index][help] */
1860 {
1861         char *display_desc = "????";
1862         int currcons = 0;
1863         int orig_x = ORIG_X;
1864         int orig_y = ORIG_Y;
1865 
1866         memset(&console_driver, 0, sizeof(struct tty_driver));
1867         console_driver.magic = TTY_DRIVER_MAGIC;
1868         console_driver.name = "tty";
1869         console_driver.name_base = 1;
1870         console_driver.major = TTY_MAJOR;
1871         console_driver.minor_start = 1;
1872         console_driver.num = MAX_NR_CONSOLES;
1873         console_driver.type = TTY_DRIVER_TYPE_CONSOLE;
1874         console_driver.init_termios = tty_std_termios;
1875         console_driver.flags = TTY_DRIVER_REAL_RAW;
1876         console_driver.refcount = &console_refcount;
1877         console_driver.table = console_table;
1878         console_driver.termios = console_termios;
1879         console_driver.termios_locked = console_termios_locked;
1880 
1881         console_driver.open = con_open;
1882         console_driver.write = con_write;
1883         console_driver.write_room = con_write_room;
1884         console_driver.chars_in_buffer = con_chars_in_buffer;
1885         console_driver.ioctl = vt_ioctl;
1886         console_driver.stop = con_stop;
1887         console_driver.start = con_start;
1888         console_driver.throttle = con_throttle;
1889         console_driver.unthrottle = con_unthrottle;
1890         
1891         if (tty_register_driver(&console_driver))
1892                 panic("Couldn't register console driver\n");
1893         
1894         con_setsize(ORIG_VIDEO_LINES, ORIG_VIDEO_COLS);
1895         video_page = ORIG_VIDEO_PAGE;                   /* never used */
1896 
1897         timer_table[BLANK_TIMER].fn = blank_screen;
1898         timer_table[BLANK_TIMER].expires = 0;
1899         if (blankinterval) {
1900                 timer_table[BLANK_TIMER].expires = jiffies+blankinterval;
1901                 timer_active |= 1<<BLANK_TIMER;
1902         }
1903         
1904         if (ORIG_VIDEO_MODE == 7)       /* Is this a monochrome display? */
1905         {
1906                 video_mem_base = 0xb0000;
1907                 video_port_reg = 0x3b4;
1908                 video_port_val = 0x3b5;
1909                 if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
1910                 {
1911                         video_type = VIDEO_TYPE_EGAM;
1912                         video_mem_term = 0xb8000;
1913                         display_desc = "EGA+";
1914                 }
1915                 else
1916                 {
1917                         video_type = VIDEO_TYPE_MDA;
1918                         video_mem_term = 0xb2000;
1919                         display_desc = "*MDA";
1920                 }
1921         }
1922         else                            /* If not, it is color. */
1923         {
1924                 can_do_color = 1;
1925                 video_mem_base = 0xb8000;
1926                 video_port_reg  = 0x3d4;
1927                 video_port_val  = 0x3d5;
1928                 if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
1929                 {
1930                         video_type = VIDEO_TYPE_EGAC;
1931                         video_mem_term = 0xc0000;
1932                         display_desc = "EGA+";
1933                 }
1934                 else
1935                 {
1936                         video_type = VIDEO_TYPE_CGA;
1937                         video_mem_term = 0xba000;
1938                         display_desc = "*CGA";
1939                 }
1940         }
1941         
1942         /* Initialize the variables used for scrolling (mostly EGA/VGA) */
1943 
1944         /* Due to kmalloc roundup allocating statically is more efficient -
1945            so provide MIN_NR_CONSOLES for people with very little memory */
1946         for (currcons = 0; currcons < MIN_NR_CONSOLES; currcons++) {
1947                 vc_cons[currcons].d = (struct vc_data *) kmem_start;
1948                 kmem_start += sizeof(struct vc_data);
1949                 vt_cons[currcons] = (struct vt_struct *) kmem_start;
1950                 kmem_start += sizeof(struct vt_struct);
1951                 vc_scrbuf[currcons] = (unsigned short *) kmem_start;
1952                 kmem_start += video_screen_size;
1953                 kmalloced = 0;
1954                 screenbuf_size = video_screen_size;
1955                 vc_init(currcons, video_num_lines, video_num_columns, currcons);
1956         }
1957 
1958         currcons = fg_console = 0;
1959 
1960         video_mem_start = video_mem_base;
1961         video_mem_end = video_mem_term;
1962         origin = video_mem_start;
1963         scr_end = video_mem_start + video_num_lines * video_size_row;
1964         gotoxy(currcons,orig_x,orig_y);
1965         printable = 1;
1966         printk("Console: %s %s %ldx%ld, %d virtual console%s (max %d)\n",
1967                 can_do_color ? "colour" : "mono",
1968                 display_desc,
1969                 video_num_columns,video_num_lines,
1970                 MIN_NR_CONSOLES, (MIN_NR_CONSOLES == 1) ? "" : "s", MAX_NR_CONSOLES);
1971         register_console(console_print);
1972         return kmem_start;
1973 }
1974 
1975 static void get_scrmem(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
1976 {
1977         memcpy((void *)vc_scrbuf[currcons], (void *)origin, video_screen_size);
1978         origin = video_mem_start = (unsigned long)vc_scrbuf[currcons];
1979         scr_end = video_mem_end = video_mem_start + video_screen_size;
1980         pos = origin + y*video_size_row + (x<<1);
1981 }
1982 
1983 static void set_scrmem(int currcons, long offset)
     /* [previous][next][first][last][top][bottom][index][help] */
1984 {
1985 #ifdef CONFIG_HGA
1986   /* This works with XFree86 1.2, 1.3 and 2.0
1987      This code could be extended and made more generally useful if we could
1988      determine the actual video mode. It appears that this should be
1989      possible on a genuine Hercules card, but I (WM) haven't been able to
1990      read from any of the required registers on my clone card.
1991      */
1992         /* This code should work with Hercules and MDA cards. */
1993         if (video_type == VIDEO_TYPE_MDA)
1994           {
1995             if (vcmode == KD_TEXT)
1996               {
1997                 /* Ensure that the card is in text mode. */
1998                 int     i;
1999                 static char herc_txt_tbl[12] = {
2000                   0x61,0x50,0x52,0x0f,0x19,6,0x19,0x19,2,0x0d,0x0b,0x0c };
2001                 outb_p(0, 0x3bf);  /* Back to power-on defaults */
2002                 outb_p(0, 0x3b8);  /* Blank the screen, select page 0, etc */
2003                 for ( i = 0 ; i < 12 ; i++ )
2004                   {
2005                     outb_p(i, 0x3b4);
2006                     outb_p(herc_txt_tbl[i], 0x3b5);
2007                   }
2008               }
2009 #define HGA_BLINKER_ON 0x20
2010 #define HGA_SCREEN_ON  8
2011             /* Make sure that the hardware is not blanked */
2012             outb_p(HGA_BLINKER_ON | HGA_SCREEN_ON, 0x3b8);
2013           }
2014 #endif CONFIG_HGA
2015 
2016         if (video_mem_term - video_mem_base < offset + video_screen_size)
2017           offset = 0;   /* strange ... */
2018         memcpy((void *)(video_mem_base + offset), (void *) origin, video_screen_size);
2019         video_mem_start = video_mem_base;
2020         video_mem_end = video_mem_term;
2021         origin = video_mem_base + offset;
2022         scr_end = origin + video_screen_size;
2023         pos = origin + y*video_size_row + (x<<1);
2024 }
2025 
2026 void blank_screen(void)
     /* [previous][next][first][last][top][bottom][index][help] */
2027 {
2028         int currcons;
2029 
2030         if (console_blanked)
2031                 return;
2032         if (!vc_cons_allocated(fg_console)) {
2033                 /* impossible */
2034                 printk("blank_screen: tty %d not allocated ??\n", fg_console+1);
2035                 return;
2036         }
2037         timer_table[BLANK_TIMER].fn = unblank_screen;
2038 
2039         /* try not to lose information by blanking, and not to waste memory */
2040         currcons = fg_console;
2041         has_scrolled = 0;
2042         blank__origin = __origin;
2043         blank_origin = origin;
2044         set_origin(fg_console);
2045         get_scrmem(fg_console);
2046         unblank_origin = origin;
2047         memsetw((void *)blank_origin, BLANK, video_mem_term-blank_origin);
2048         hide_cursor();
2049         console_blanked = fg_console + 1;
2050 }
2051 
2052 void unblank_screen(void)
     /* [previous][next][first][last][top][bottom][index][help] */
2053 {
2054         int currcons;
2055         int resetorg;
2056         long offset;
2057 
2058         if (!console_blanked)
2059                 return;
2060         if (!vc_cons_allocated(fg_console)) {
2061                 /* impossible */
2062                 printk("unblank_screen: tty %d not allocated ??\n", fg_console+1);
2063                 return;
2064         }
2065         timer_table[BLANK_TIMER].fn = blank_screen;
2066         if (blankinterval) {
2067                 timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
2068                 timer_active |= 1<<BLANK_TIMER;
2069         }
2070         currcons = fg_console;
2071         offset = 0;
2072         resetorg = 0;
2073         if (console_blanked == fg_console + 1 && origin == unblank_origin
2074             && !has_scrolled) {
2075                 /* try to restore the exact situation before blanking */
2076                 resetorg = 1;
2077                 offset = (blank_origin - video_mem_base)
2078                         - (unblank_origin - video_mem_start);
2079         }
2080 
2081         console_blanked = 0;
2082         set_scrmem(fg_console, offset);
2083         set_origin(fg_console);
2084         set_cursor(fg_console);
2085         if (resetorg)
2086                 __set_origin(blank__origin);
2087 }
2088 
2089 void update_screen(int new_console)
     /* [previous][next][first][last][top][bottom][index][help] */
2090 {
2091         static int lock = 0;
2092 
2093         if (new_console == fg_console || lock)
2094                 return;
2095         if (!vc_cons_allocated(new_console)) {
2096                 /* strange ... */
2097                 printk("update_screen: tty %d not allocated ??\n", new_console+1);
2098                 return;
2099         }
2100         lock = 1;
2101 #ifdef CONFIG_SELECTION
2102         highlight_pointer(fg_console,-1);
2103 #endif /* CONFIG_SELECTION */
2104         if (!console_blanked)
2105                 get_scrmem(fg_console);
2106         else
2107                 console_blanked = -1;      /* no longer of the form console+1 */
2108         fg_console = new_console; /* this is the only (nonzero) assignment to fg_console */
2109                                   /* consequently, fg_console will always be allocated */
2110         set_scrmem(fg_console, 0); 
2111         set_origin(fg_console);
2112         set_cursor(fg_console);
2113         set_leds();
2114         compute_shiftstate();
2115         lock = 0;
2116 }
2117 
2118 int do_screendump(int arg)
     /* [previous][next][first][last][top][bottom][index][help] */
2119 {
2120         char *sptr, *buf = (char *)arg;
2121         int currcons, l;
2122 
2123         if (!suser())
2124                 return -EPERM;
2125         l = verify_area(VERIFY_READ, buf, 2);
2126         if (l)
2127                 return l;
2128         currcons = get_fs_byte(buf+1);
2129         currcons = (currcons ? currcons-1 : fg_console);
2130         if (!vc_cons_allocated(currcons))
2131                 return -EIO;
2132         l = verify_area(VERIFY_WRITE, buf, 2+video_num_columns*video_num_lines);
2133         if (l)
2134                 return l;
2135         put_fs_byte((char)(video_num_lines),buf++);   
2136         put_fs_byte((char)(video_num_columns),buf++);
2137         sptr = (char *) origin;
2138         for (l=video_num_lines*video_num_columns; l>0 ; l--, sptr++)
2139                 put_fs_byte(*sptr++,buf++);     
2140         return(0);
2141 }
2142 
2143 /*
2144  * Allocate the console screen memory.
2145  */
2146 int con_open(struct tty_struct *tty, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
2147 {
2148         unsigned int    idx;
2149         int i;
2150 
2151         idx = MINOR(tty->device) - tty->driver.minor_start;
2152         
2153         i = vc_allocate(idx);
2154         if (i)
2155                 return i;
2156 
2157         vt_cons[idx]->vc_num = idx;
2158         tty->driver_data = vt_cons[idx];
2159         
2160         if (!tty->winsize.ws_row && !tty->winsize.ws_col) {
2161                 tty->winsize.ws_row = video_num_lines;
2162                 tty->winsize.ws_col = video_num_columns;
2163         }
2164         return 0;
2165 }
2166 
2167 #ifdef CONFIG_SELECTION
2168 /* correction factor for when screen is hardware-scrolled */
2169 #define hwscroll_offset (currcons == fg_console ? ((__real_origin - __origin) << 1) : 0)
2170 
2171 /* set reverse video on characters s-e of console with selection. */
2172 static void highlight(const int currcons, const int s, const int e)
     /* [previous][next][first][last][top][bottom][index][help] */
2173 {
2174         unsigned char *p, *p1, *p2;
2175 
2176         p1 = (unsigned char *)origin - hwscroll_offset + s + 1;
2177         p2 = (unsigned char *)origin - hwscroll_offset + e + 1;
2178         if (p1 > p2)
2179         {
2180                 p = p1;
2181                 p1 = p2;
2182                 p2 = p;
2183         }
2184         for (p = p1; p <= p2; p += 2)
2185                 *p = (*p & 0x88) | ((*p << 4) & 0x70) | ((*p >> 4) & 0x07);
2186 }
2187 
2188 /* use complementary color to show the pointer */
2189 static void highlight_pointer(const int currcons, const int where)
     /* [previous][next][first][last][top][bottom][index][help] */
2190 {
2191         unsigned char *p;
2192         static unsigned char *prev=NULL;
2193 
2194         if (where==-1) /* remove the pointer */
2195         {
2196                 if (prev)
2197                 {
2198                         *prev ^= 0x77;
2199                         prev=NULL;
2200                 }
2201         }
2202         else
2203         {
2204                 p = (unsigned char *)origin - hwscroll_offset + where + 1;
2205                 *p ^= 0x77;
2206                 if (prev) *prev ^= 0x77; /* remove the previous one */
2207                 prev=p;
2208         }
2209 }
2210 
2211 
2212 /*
2213  * This function uses a 128-bit look up table
2214  */
2215 static unsigned long inwordLut[4]={
2216   0x00000000, /* control chars     */
2217   0x03FF0000, /* digits            */
2218   0x87FFFFFE, /* uppercase and '_' */
2219   0x07FFFFFE  /* lowercase         */
2220 };
2221 static inline int inword(const char c) {
     /* [previous][next][first][last][top][bottom][index][help] */
2222    return ( inwordLut[(c>>5)&3] >> (c&0x1F) ) & 1;
2223 }
2224 
2225 /* set inwordLut contents. Invoked by ioctl(). */
2226 int sel_loadlut(const int arg)
     /* [previous][next][first][last][top][bottom][index][help] */
2227 {
2228     memcpy_fromfs(inwordLut,(unsigned long *)(arg+4),16);
2229     return 0;
2230 }
2231 
2232 /* does screen address p correspond to character at LH/RH edge of screen? */
2233 static inline int atedge(const int p)
     /* [previous][next][first][last][top][bottom][index][help] */
2234 {
2235         return (!(p % video_size_row) || !((p + 2) % video_size_row));
2236 }
2237 
2238 /* constrain v such that l <= v <= u */
2239 static inline short limit(const int v, const int l, const int u)
     /* [previous][next][first][last][top][bottom][index][help] */
2240 {
2241         return (v < l) ? l : ((v > u) ? u : v);
2242 }
2243 
2244 /* invoked via ioctl(TIOCLINUX) */
2245 int mouse_reporting(void)
     /* [previous][next][first][last][top][bottom][index][help] */
2246 {
2247         int currcons = fg_console;
2248 
2249         return report_mouse;
2250 }
2251 
2252 /* set the current selection. Invoked by ioctl(). */
2253 int set_selection(const int arg, struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
2254 {
2255         unsigned short *args, xs, ys, xe, ye;
2256         int currcons = fg_console;
2257         int sel_mode, new_sel_start, new_sel_end, spc;
2258         char *bp, *obp, *spos;
2259         int i, ps, pe;
2260         char *off = (char *)origin - hwscroll_offset;
2261 
2262         unblank_screen();
2263         args = (unsigned short *)(arg + 1);
2264         xs = get_fs_word(args++) - 1;
2265         ys = get_fs_word(args++) - 1;
2266         xe = get_fs_word(args++) - 1;
2267         ye = get_fs_word(args++) - 1;
2268         sel_mode = get_fs_word(args);
2269 
2270         xs = limit(xs, 0, video_num_columns - 1);
2271         ys = limit(ys, 0, video_num_lines - 1);
2272         xe = limit(xe, 0, video_num_columns - 1);
2273         ye = limit(ye, 0, video_num_lines - 1);
2274         ps = ys * video_size_row + (xs << 1);
2275         pe = ye * video_size_row + (xe << 1);
2276 
2277         if (report_mouse && (sel_mode & 16)) {
2278                 mouse_report(currcons, tty, sel_mode & 15, xs, ys);
2279                 return 0;
2280         }
2281 
2282         if (ps > pe)    /* make sel_start <= sel_end */
2283         {
2284                 int tmp = ps;
2285                 ps = pe;
2286                 pe = tmp;
2287         }
2288 
2289         switch (sel_mode)
2290         {
2291                 case 0: /* character-by-character selection */
2292                         new_sel_start = ps;
2293                         new_sel_end = pe;
2294                         break;
2295                 case 1: /* word-by-word selection */
2296                         spc = isspace(*(off + ps));
2297                         for (new_sel_start = ps; ; ps -= 2)
2298                         {
2299                                 if ((spc && !isspace(*(off + ps))) ||
2300                                     (!spc && !inword(*(off + ps))))
2301                                         break;
2302                                 new_sel_start = ps;
2303                                 if (!(ps % video_size_row))
2304                                         break;
2305                         }
2306                         spc = isspace(*(off + pe));
2307                         for (new_sel_end = pe; ; pe += 2)
2308                         {
2309                                 if ((spc && !isspace(*(off + pe))) ||
2310                                     (!spc && !inword(*(off + pe))))
2311                                         break;
2312                                 new_sel_end = pe;
2313                                 if (!((pe + 2) % video_size_row))
2314                                         break;
2315                         }
2316                         break;
2317                 case 2: /* line-by-line selection */
2318                         new_sel_start = ps - ps % video_size_row;
2319                         new_sel_end = pe + video_size_row
2320                                     - pe % video_size_row - 2;
2321                         break;
2322                 case 3: /* pointer highlight */
2323                         if (sel_cons != currcons)
2324                         {
2325                                 highlight_pointer(sel_cons,-1);
2326                                 clear_selection();
2327                                 sel_cons = currcons;
2328                         }
2329                         highlight_pointer(sel_cons,pe);
2330                         return 0; /* nothing more */
2331                 default:
2332                         return -EINVAL;
2333         }
2334         /* select to end of line if on trailing space */
2335         if (new_sel_end > new_sel_start &&
2336                 !atedge(new_sel_end) && isspace(*(off + new_sel_end)))
2337         {
2338                 for (pe = new_sel_end + 2; ; pe += 2)
2339                 {
2340                         if (!isspace(*(off + pe)) || atedge(pe))
2341                                 break;
2342                 }
2343                 if (isspace(*(off + pe)))
2344                         new_sel_end = pe;
2345         }
2346         if (sel_cons != currcons)
2347         {
2348                 clear_selection();
2349                 sel_cons = currcons;
2350         }
2351         if (sel_start == -1)    /* no current selection */
2352                 highlight(sel_cons, new_sel_start, new_sel_end);
2353         else if (new_sel_start == sel_start)
2354         {
2355                 if (new_sel_end == sel_end)     /* no action required */
2356                         return 0;
2357                 else if (new_sel_end > sel_end) /* extend to right */
2358                         highlight(sel_cons, sel_end + 2, new_sel_end);
2359                 else                            /* contract from right */
2360                         highlight(sel_cons, new_sel_end + 2, sel_end);
2361         }
2362         else if (new_sel_end == sel_end)
2363         {
2364                 if (new_sel_start < sel_start)  /* extend to left */
2365                         highlight(sel_cons, new_sel_start, sel_start - 2);
2366                 else                            /* contract from left */
2367                         highlight(sel_cons, sel_start, new_sel_start - 2);
2368         }
2369         else    /* some other case; start selection from scratch */
2370         {
2371                 clear_selection();
2372                 highlight(sel_cons, new_sel_start, new_sel_end);
2373         }
2374         sel_start = new_sel_start;
2375         sel_end = new_sel_end;
2376         obp = bp = sel_buffer;
2377         for (i = sel_start; i <= sel_end; i += 2)
2378         {
2379                 spos = (char *)off + i;
2380                 *bp++ = *spos;
2381                 if (!isspace(*spos))
2382                         obp = bp;
2383                 if (! ((i + 2) % video_size_row))
2384                 {
2385                         /* strip trailing blanks from line and add newline,
2386                            unless non-space at end of line. */
2387                         if (obp != bp)
2388                         {
2389                                 bp = obp;
2390                                 *bp++ = '\r';
2391                         }
2392                         obp = bp;
2393                 }
2394                 /* check for space, leaving room for next character, possible
2395                    newline, and null at end. */
2396                 if (bp - sel_buffer > SEL_BUFFER_SIZE - 3)
2397                         break;
2398         }
2399         *bp = '\0';
2400         return 0;
2401 }
2402 
2403 /* insert the contents of the selection buffer into the queue of the
2404    tty associated with the current console. Invoked by ioctl(). */
2405 int paste_selection(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
2406 {
2407         struct wait_queue wait = { current, NULL };
2408         char    *bp = sel_buffer;
2409         int     c, l;
2410         struct vt_struct *vt = (struct vt_struct *) tty->driver_data;
2411         
2412         if (!sel_buffer[0])
2413                 return 0;
2414         unblank_screen();
2415         c = strlen(sel_buffer);
2416         current->state = TASK_INTERRUPTIBLE;
2417         add_wait_queue(&vt->paste_wait, &wait);
2418         while (c) {
2419                 if (test_bit(TTY_THROTTLED, &tty->flags)) {
2420                         schedule();
2421                         continue;
2422                 }
2423                 l = MIN(c, tty->ldisc.receive_room(tty));
2424                 tty->ldisc.receive_buf(tty, bp, 0, l);
2425                 c -= l;
2426                 bp += l;
2427         }
2428         current->state = TASK_RUNNING;
2429         return 0;
2430 }
2431 
2432 /* remove the current selection highlight, if any, from the console holding
2433    the selection. */
2434 static void clear_selection()
     /* [previous][next][first][last][top][bottom][index][help] */
2435 {
2436         highlight_pointer(sel_cons, -1); /* hide the pointer */
2437         if (sel_start != -1)
2438         {
2439                 highlight(sel_cons, sel_start, sel_end);
2440                 sel_start = -1;
2441         }
2442 }
2443 #endif /* CONFIG_SELECTION */
2444 
2445 /*
2446  * PIO_FONT support.
2447  *
2448  * The font loading code goes back to the codepage package by
2449  * Joel Hoffman (joel@wam.umd.edu). (He reports that the original
2450  * reference is: "From: p. 307 of _Programmer's Guide to PC & PS/2
2451  * Video Systems_ by Richard Wilton. 1987.  Microsoft Press".)
2452  *
2453  * Change for certain monochrome monitors by Yury Shevchuck
2454  * (sizif@botik.yaroslavl.su).
2455  */
2456 
2457 #define colourmap ((char *)0xa0000)
2458 /* Pauline Middelink reports that we should use 0xA0000 for the bwmap as well.. */
2459 #define blackwmap ((char *)0xa0000)
2460 #define cmapsz 8192
2461 #define seq_port_reg (0x3c4)
2462 #define seq_port_val (0x3c5)
2463 #define gr_port_reg (0x3ce)
2464 #define gr_port_val (0x3cf)
2465 
2466 static int set_get_font(char * arg, int set)
     /* [previous][next][first][last][top][bottom][index][help] */
2467 {
2468 #ifdef CAN_LOAD_EGA_FONTS
2469         int i;
2470         char *charmap;
2471         int beg;
2472 
2473         /* no use to "load" CGA... */
2474 
2475         if (video_type == VIDEO_TYPE_EGAC) {
2476                 charmap = colourmap;
2477                 beg = 0x0e;
2478         } else if (video_type == VIDEO_TYPE_EGAM) {
2479                 charmap = blackwmap;
2480                 beg = 0x0a;
2481         } else
2482                 return -EINVAL;
2483 
2484         i = verify_area(set ? VERIFY_READ : VERIFY_WRITE, (void *)arg, cmapsz);
2485         if (i)
2486                 return i;
2487 
2488         cli();
2489         outb_p( 0x00, seq_port_reg );   /* First, the sequencer */
2490         outb_p( 0x01, seq_port_val );   /* Synchronous reset */
2491         outb_p( 0x02, seq_port_reg );
2492         outb_p( 0x04, seq_port_val );   /* CPU writes only to map 2 */
2493         outb_p( 0x04, seq_port_reg );
2494         outb_p( 0x07, seq_port_val );   /* Sequential addressing */
2495         outb_p( 0x00, seq_port_reg );
2496         outb_p( 0x03, seq_port_val );   /* Clear synchronous reset */
2497 
2498         outb_p( 0x04, gr_port_reg );    /* Now, the graphics controller */
2499         outb_p( 0x02, gr_port_val );    /* select map 2 */
2500         outb_p( 0x05, gr_port_reg );
2501         outb_p( 0x00, gr_port_val );    /* disable odd-even addressing */
2502         outb_p( 0x06, gr_port_reg );
2503         outb_p( 0x00, gr_port_val );    /* map start at A000:0000 */
2504         sti();
2505 
2506         if (set)
2507                 for (i=0; i<cmapsz ; i++)
2508                         *(charmap+i) = get_fs_byte(arg+i);
2509         else
2510                 for (i=0; i<cmapsz ; i++)
2511                         put_fs_byte(*(charmap+i), arg+i);
2512 
2513         cli();
2514         outb_p( 0x00, seq_port_reg );   /* First, the sequencer */
2515         outb_p( 0x01, seq_port_val );   /* Synchronous reset */
2516         outb_p( 0x02, seq_port_reg );
2517         outb_p( 0x03, seq_port_val );   /* CPU writes to maps 0 and 1 */
2518         outb_p( 0x04, seq_port_reg );
2519         outb_p( 0x03, seq_port_val );   /* odd-even addressing */
2520         outb_p( 0x00, seq_port_reg );
2521         outb_p( 0x03, seq_port_val );   /* clear synchronous reset */
2522 
2523         outb_p( 0x04, gr_port_reg );    /* Now, the graphics controller */
2524         outb_p( 0x00, gr_port_val );    /* select map 0 for CPU */
2525         outb_p( 0x05, gr_port_reg );
2526         outb_p( 0x10, gr_port_val );    /* enable even-odd addressing */
2527         outb_p( 0x06, gr_port_reg );
2528         outb_p( beg, gr_port_val );     /* map starts at b800:0 or b000:0 */
2529         sti();
2530 
2531         return 0;
2532 #else
2533         return -EINVAL;
2534 #endif
2535 }
2536 
2537 /*
2538  * Load font into the EGA/VGA character generator. arg points to a 8192
2539  * byte map, 32 bytes per character. Only first H of them are used for
2540  * 8xH fonts (0 < H <= 32).
2541  */
2542 
2543 int con_set_font (char *arg)
     /* [previous][next][first][last][top][bottom][index][help] */
2544 {
2545         return set_get_font (arg,1);
2546 }
2547 
2548 int con_get_font (char *arg)
     /* [previous][next][first][last][top][bottom][index][help] */
2549 {
2550         return set_get_font (arg,0);
2551 }
2552 
2553 /*
2554  * Load customizable translation table (USER_TRANS[]). All checks are here,
2555  * so we need only include 'return con_set_trans(arg)' in the ioctl handler
2556  * arg points to a 256 byte translation table.
2557  */
2558 int con_set_trans(char * arg)
     /* [previous][next][first][last][top][bottom][index][help] */
2559 {
2560         int i;
2561 
2562         i = verify_area(VERIFY_READ, (void *)arg, E_TABSZ);
2563         if (i)
2564                 return i;
2565 
2566         for (i=0; i<E_TABSZ ; i++) USER_TRANS[i] = get_fs_byte(arg+i);
2567         USER_TRANS[012]=0;
2568         USER_TRANS[014]=0;
2569         USER_TRANS[015]=0;
2570         USER_TRANS[033]=0;
2571         return 0;
2572 }
2573 
2574 int con_get_trans(char * arg)
     /* [previous][next][first][last][top][bottom][index][help] */
2575 {
2576         int i;
2577 
2578         i = verify_area(VERIFY_WRITE, (void *)arg, E_TABSZ);
2579         if (i)
2580                 return i;
2581 
2582         for (i=0; i<E_TABSZ ; i++) put_fs_byte(USER_TRANS[i],arg+i);
2583         return 0;
2584 }

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