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

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