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         if (!suser())
2156                 return -EPERM;
2157         l = verify_area(VERIFY_READ, buf, 2);
2158         if (l)
2159                 return l;
2160         currcons = get_fs_byte(buf+1);
2161         currcons = (currcons ? currcons-1 : fg_console);
2162         if (!vc_cons_allocated(currcons))
2163                 return -EIO;
2164         
2165         /* mode 0 needs 2+wd*ht, modes 1 and 2 need 4+2*wd*ht */
2166         chcount=video_num_columns*video_num_lines;
2167         l = verify_area(mode==2 ? VERIFY_READ :VERIFY_WRITE,
2168                 buf, (2+chcount)*(mode ? 2 : 1));
2169         if (l)
2170                 return l;
2171         if (mode<2) {
2172         put_fs_byte((char)(video_num_lines),buf++);   
2173         put_fs_byte((char)(video_num_columns),buf++);
2174             }
2175 #ifdef CONFIG_SELECTION
2176         clear_selection();
2177 #endif
2178         switch(mode) {
2179             case 0:
2180                         sptr = (char *) origin;
2181                         for (l=chcount; l>0 ; l--, sptr++)
2182                                 put_fs_byte(*sptr++,buf++);     
2183                         break;
2184             case 1:
2185                         put_fs_byte((char)x,buf++); put_fs_byte((char)y,buf++); 
2186                         memcpy_tofs(buf,(char *)origin,2*chcount);
2187                         break;
2188             case 2:
2189                         gotoxy(currcons, get_fs_byte(buf+2), get_fs_byte(buf+3));
2190                         buf+=4; /* ioctl#, console#, x,y */
2191                         memcpy_fromfs((char *)origin,buf,2*chcount);
2192                         break;
2193             }
2194         return(0);
2195 }
2196 
2197 /*
2198  * Allocate the console screen memory.
2199  */
2200 int con_open(struct tty_struct *tty, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
2201 {
2202         unsigned int    idx;
2203         int i;
2204 
2205         idx = MINOR(tty->device) - tty->driver.minor_start;
2206         
2207         i = vc_allocate(idx);
2208         if (i)
2209                 return i;
2210 
2211         vt_cons[idx]->vc_num = idx;
2212         tty->driver_data = vt_cons[idx];
2213         
2214         if (!tty->winsize.ws_row && !tty->winsize.ws_col) {
2215                 tty->winsize.ws_row = video_num_lines;
2216                 tty->winsize.ws_col = video_num_columns;
2217         }
2218         return 0;
2219 }
2220 
2221 #ifdef CONFIG_SELECTION
2222 /* correction factor for when screen is hardware-scrolled */
2223 #define hwscroll_offset (currcons == fg_console ? ((__real_origin - __origin) << 1) : 0)
2224 
2225 /* set reverse video on characters s-e of console with selection. */
2226 static void highlight(const int currcons, const int s, const int e)
     /* [previous][next][first][last][top][bottom][index][help] */
2227 {
2228         unsigned char *p, *p1, *p2;
2229 
2230         p1 = (unsigned char *)origin - hwscroll_offset + s + 1;
2231         p2 = (unsigned char *)origin - hwscroll_offset + e + 1;
2232 
2233         for (p = p1; p <= p2; p += 2)
2234                 *p = (*p & 0x88) | ((*p << 4) & 0x70) | ((*p >> 4) & 0x07);
2235 }
2236 
2237 /* use complementary color to show the pointer */
2238 static void highlight_pointer(const int currcons, const int where)
     /* [previous][next][first][last][top][bottom][index][help] */
2239 {
2240         unsigned char *p;
2241         static unsigned char *prev=NULL;
2242 
2243         if (where==-1) /* remove the pointer */
2244         {
2245                 if (prev)
2246                 {
2247                         *prev ^= 0x77;
2248                         prev=NULL;
2249                 }
2250         }
2251         else
2252         {
2253                 p = (unsigned char *)origin - hwscroll_offset + where + 1;
2254                 *p ^= 0x77;
2255                 if (prev) *prev ^= 0x77; /* remove the previous one */
2256                 prev=p;
2257         }
2258 }
2259 
2260 
2261 /*
2262  * This function uses a 128-bit look up table
2263  * WARNING: This depends on both endianness and the ascii code
2264  */
2265 static unsigned long inwordLut[4]={
2266   0x00000000, /* control chars     */
2267   0x03FF0000, /* digits            */
2268   0x87FFFFFE, /* uppercase and '_' */
2269   0x07FFFFFE  /* lowercase         */
2270 };
2271 static inline int inword(const char c) {
     /* [previous][next][first][last][top][bottom][index][help] */
2272    return ( inwordLut[(c>>5)&3] >> (c&0x1F) ) & 1;
2273 }
2274 
2275 /* set inwordLut contents. Invoked by ioctl(). */
2276 int sel_loadlut(const int arg)
     /* [previous][next][first][last][top][bottom][index][help] */
2277 {
2278     memcpy_fromfs(inwordLut,(unsigned long *)(arg+4),16);
2279     return 0;
2280 }
2281 
2282 /* does screen address p correspond to character at LH/RH edge of screen? */
2283 static inline int atedge(const int p)
     /* [previous][next][first][last][top][bottom][index][help] */
2284 {
2285         return (!(p % video_size_row) || !((p + 2) % video_size_row));
2286 }
2287 
2288 /* constrain v such that v <= u */
2289 static inline unsigned short limit(const unsigned short v, const unsigned short u)
     /* [previous][next][first][last][top][bottom][index][help] */
2290 {
2291 /* gcc miscompiles the ?: operator, so don't use it.. */
2292         if (v > u)
2293                 return u;
2294         return v;
2295 }
2296 
2297 /* invoked via ioctl(TIOCLINUX) */
2298 int mouse_reporting(void)
     /* [previous][next][first][last][top][bottom][index][help] */
2299 {
2300         int currcons = fg_console;
2301 
2302         return report_mouse;
2303 }
2304 
2305 /* set the current selection. Invoked by ioctl(). */
2306 int set_selection(const int arg, struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
2307 {
2308         unsigned short *args, xs, ys, xe, ye;
2309         int currcons = fg_console;
2310         int sel_mode, new_sel_start, new_sel_end, spc;
2311         char *bp, *obp, *spos;
2312         int i, ps, pe;
2313         char *off = (char *)origin - hwscroll_offset;
2314 
2315         unblank_screen();
2316         args = (unsigned short *)(arg + 1);
2317         xs = get_fs_word(args++) - 1;
2318         ys = get_fs_word(args++) - 1;
2319         xe = get_fs_word(args++) - 1;
2320         ye = get_fs_word(args++) - 1;
2321         sel_mode = get_fs_word(args);
2322 
2323         xs = limit(xs, video_num_columns - 1);
2324         ys = limit(ys, video_num_lines - 1);
2325         xe = limit(xe, video_num_columns - 1);
2326         ye = limit(ye, video_num_lines - 1);
2327         ps = ys * video_size_row + (xs << 1);
2328         pe = ye * video_size_row + (xe << 1);
2329 
2330         if (report_mouse && (sel_mode & 16)) {
2331                 mouse_report(currcons, tty, sel_mode & 15, xs, ys);
2332                 return 0;
2333         }
2334 
2335         if (ps > pe)    /* make sel_start <= sel_end */
2336         {
2337                 int tmp = ps;
2338                 ps = pe;
2339                 pe = tmp;
2340         }
2341 
2342         switch (sel_mode)
2343         {
2344                 case 0: /* character-by-character selection */
2345                         new_sel_start = ps;
2346                         new_sel_end = pe;
2347                         break;
2348                 case 1: /* word-by-word selection */
2349                         spc = isspace(*(off + ps));
2350                         for (new_sel_start = ps; ; ps -= 2)
2351                         {
2352                                 if ((spc && !isspace(*(off + ps))) ||
2353                                     (!spc && !inword(*(off + ps))))
2354                                         break;
2355                                 new_sel_start = ps;
2356                                 if (!(ps % video_size_row))
2357                                         break;
2358                         }
2359                         spc = isspace(*(off + pe));
2360                         for (new_sel_end = pe; ; pe += 2)
2361                         {
2362                                 if ((spc && !isspace(*(off + pe))) ||
2363                                     (!spc && !inword(*(off + pe))))
2364                                         break;
2365                                 new_sel_end = pe;
2366                                 if (!((pe + 2) % video_size_row))
2367                                         break;
2368                         }
2369                         break;
2370                 case 2: /* line-by-line selection */
2371                         new_sel_start = ps - ps % video_size_row;
2372                         new_sel_end = pe + video_size_row
2373                                     - pe % video_size_row - 2;
2374                         break;
2375                 case 3: /* pointer highlight */
2376                         if (sel_cons != currcons)
2377                         {
2378                                 clear_selection();
2379                                 sel_cons = currcons;
2380                         }
2381                         highlight_pointer(sel_cons,pe);
2382                         return 0; /* nothing more */
2383                 default:
2384                         return -EINVAL;
2385         }
2386         /* remove the pointer */
2387         highlight_pointer(sel_cons,-1);
2388         /* select to end of line if on trailing space */
2389         if (new_sel_end > new_sel_start &&
2390                 !atedge(new_sel_end) && isspace(*(off + new_sel_end)))
2391         {
2392                 for (pe = new_sel_end + 2; ; pe += 2)
2393                 {
2394                         if (!isspace(*(off + pe)) || atedge(pe))
2395                                 break;
2396                 }
2397                 if (isspace(*(off + pe)))
2398                         new_sel_end = pe;
2399         }
2400         if (sel_cons != currcons)
2401         {
2402                 clear_selection();
2403                 sel_cons = currcons;
2404         }
2405         if (sel_start == -1)    /* no current selection */
2406                 highlight(sel_cons, new_sel_start, new_sel_end);
2407         else if (new_sel_start == sel_start)
2408         {
2409                 if (new_sel_end == sel_end)     /* no action required */
2410                         return 0;
2411                 else if (new_sel_end > sel_end) /* extend to right */
2412                         highlight(sel_cons, sel_end + 2, new_sel_end);
2413                 else                            /* contract from right */
2414                         highlight(sel_cons, new_sel_end + 2, sel_end);
2415         }
2416         else if (new_sel_end == sel_end)
2417         {
2418                 if (new_sel_start < sel_start)  /* extend to left */
2419                         highlight(sel_cons, new_sel_start, sel_start - 2);
2420                 else                            /* contract from left */
2421                         highlight(sel_cons, sel_start, new_sel_start - 2);
2422         }
2423         else    /* some other case; start selection from scratch */
2424         {
2425                 clear_selection();
2426                 highlight(sel_cons, new_sel_start, new_sel_end);
2427         }
2428         sel_start = new_sel_start;
2429         sel_end = new_sel_end;
2430 
2431         /* realloc the buffer (it seems to be efficient, anyway) */
2432         if (sel_buffer) kfree(sel_buffer);
2433         sel_buffer = kmalloc((sel_end-sel_start)/2+2, GFP_KERNEL);
2434         if (!sel_buffer)
2435         {
2436                 printk("selection: kmalloc() failed\n");
2437                 clear_selection();
2438                 return (0); /* is it right? */
2439         }
2440         obp = bp = sel_buffer;
2441         for (i = sel_start; i <= sel_end; i += 2)
2442         {
2443                 spos = (char *)off + i;
2444                 *bp++ = *spos;
2445                 if (!isspace(*spos))
2446                         obp = bp;
2447                 if (! ((i + 2) % video_size_row))
2448                 {
2449                         /* strip trailing blanks from line and add newline,
2450                            unless non-space at end of line. */
2451                         if (obp != bp)
2452                         {
2453                                 bp = obp;
2454                                 *bp++ = '\r';
2455                         }
2456                         obp = bp;
2457                 }
2458         }
2459         *bp = '\0';
2460         return 0;
2461 }
2462 
2463 /* insert the contents of the selection buffer into the queue of the
2464    tty associated with the current console. Invoked by ioctl(). */
2465 int paste_selection(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
2466 {
2467         struct wait_queue wait = { current, NULL };
2468         char    *bp = sel_buffer;
2469         int     c, l;
2470         struct vt_struct *vt = (struct vt_struct *) tty->driver_data;
2471         
2472         if (!bp || !bp[0])
2473                 return 0;
2474         unblank_screen();
2475         c = strlen(sel_buffer);
2476         current->state = TASK_INTERRUPTIBLE;
2477         add_wait_queue(&vt->paste_wait, &wait);
2478         while (c) {
2479                 if (test_bit(TTY_THROTTLED, &tty->flags)) {
2480                         schedule();
2481                         continue;
2482                 }
2483                 l = MIN(c, tty->ldisc.receive_room(tty));
2484                 tty->ldisc.receive_buf(tty, bp, 0, l);
2485                 c -= l;
2486                 bp += l;
2487         }
2488         current->state = TASK_RUNNING;
2489         return 0;
2490 }
2491 
2492 /* remove the current selection highlight, if any, from the console holding
2493    the selection. */
2494 static void clear_selection()
     /* [previous][next][first][last][top][bottom][index][help] */
2495 {
2496         highlight_pointer(sel_cons, -1); /* hide the pointer */
2497         if (sel_start != -1)
2498         {
2499                 highlight(sel_cons, sel_start, sel_end);
2500                 sel_start = -1;
2501         }
2502 }
2503 #endif /* CONFIG_SELECTION */
2504 
2505 /*
2506  * PIO_FONT support.
2507  *
2508  * The font loading code goes back to the codepage package by
2509  * Joel Hoffman (joel@wam.umd.edu). (He reports that the original
2510  * reference is: "From: p. 307 of _Programmer's Guide to PC & PS/2
2511  * Video Systems_ by Richard Wilton. 1987.  Microsoft Press".)
2512  *
2513  * Change for certain monochrome monitors by Yury Shevchuck
2514  * (sizif@botik.yaroslavl.su).
2515  */
2516 
2517 #define colourmap ((char *)0xa0000)
2518 /* Pauline Middelink <middelin@polyware.iaf.nl> reports that we
2519    should use 0xA0000 for the bwmap as well.. */
2520 #define blackwmap ((char *)0xa0000)
2521 #define cmapsz 8192
2522 #define seq_port_reg (0x3c4)
2523 #define seq_port_val (0x3c5)
2524 #define gr_port_reg (0x3ce)
2525 #define gr_port_val (0x3cf)
2526 
2527 static int set_get_font(char * arg, int set)
     /* [previous][next][first][last][top][bottom][index][help] */
2528 {
2529 #ifdef CAN_LOAD_EGA_FONTS
2530         int i;
2531         char *charmap;
2532         int beg;
2533 
2534         /* no use to "load" CGA... */
2535 
2536         if (video_type == VIDEO_TYPE_EGAC) {
2537                 charmap = colourmap;
2538                 beg = 0x0e;
2539         } else if (video_type == VIDEO_TYPE_EGAM) {
2540                 charmap = blackwmap;
2541                 beg = 0x0a;
2542         } else
2543                 return -EINVAL;
2544 
2545         i = verify_area(set ? VERIFY_READ : VERIFY_WRITE, (void *)arg, cmapsz);
2546         if (i)
2547                 return i;
2548 
2549         cli();
2550         outb_p( 0x00, seq_port_reg );   /* First, the sequencer */
2551         outb_p( 0x01, seq_port_val );   /* Synchronous reset */
2552         outb_p( 0x02, seq_port_reg );
2553         outb_p( 0x04, seq_port_val );   /* CPU writes only to map 2 */
2554         outb_p( 0x04, seq_port_reg );
2555         outb_p( 0x07, seq_port_val );   /* Sequential addressing */
2556         outb_p( 0x00, seq_port_reg );
2557         outb_p( 0x03, seq_port_val );   /* Clear synchronous reset */
2558 
2559         outb_p( 0x04, gr_port_reg );    /* Now, the graphics controller */
2560         outb_p( 0x02, gr_port_val );    /* select map 2 */
2561         outb_p( 0x05, gr_port_reg );
2562         outb_p( 0x00, gr_port_val );    /* disable odd-even addressing */
2563         outb_p( 0x06, gr_port_reg );
2564         outb_p( 0x00, gr_port_val );    /* map start at A000:0000 */
2565         sti();
2566 
2567         if (set)
2568                 for (i=0; i<cmapsz ; i++)
2569                         *(charmap+i) = get_fs_byte(arg+i);
2570         else
2571                 for (i=0; i<cmapsz ; i++)
2572                         put_fs_byte(*(charmap+i), arg+i);
2573 
2574         cli();
2575         outb_p( 0x00, seq_port_reg );   /* First, the sequencer */
2576         outb_p( 0x01, seq_port_val );   /* Synchronous reset */
2577         outb_p( 0x02, seq_port_reg );
2578         outb_p( 0x03, seq_port_val );   /* CPU writes to maps 0 and 1 */
2579         outb_p( 0x04, seq_port_reg );
2580         outb_p( 0x03, seq_port_val );   /* odd-even addressing */
2581         outb_p( 0x00, seq_port_reg );
2582         outb_p( 0x03, seq_port_val );   /* clear synchronous reset */
2583 
2584         outb_p( 0x04, gr_port_reg );    /* Now, the graphics controller */
2585         outb_p( 0x00, gr_port_val );    /* select map 0 for CPU */
2586         outb_p( 0x05, gr_port_reg );
2587         outb_p( 0x10, gr_port_val );    /* enable even-odd addressing */
2588         outb_p( 0x06, gr_port_reg );
2589         outb_p( beg, gr_port_val );     /* map starts at b800:0 or b000:0 */
2590         sti();
2591 
2592         return 0;
2593 #else
2594         return -EINVAL;
2595 #endif
2596 }
2597 
2598 /*
2599  * Load font into the EGA/VGA character generator. arg points to a 8192
2600  * byte map, 32 bytes per character. Only first H of them are used for
2601  * 8xH fonts (0 < H <= 32).
2602  */
2603 
2604 int con_set_font (char *arg)
     /* [previous][next][first][last][top][bottom][index][help] */
2605 {
2606         return set_get_font (arg,1);
2607 }
2608 
2609 int con_get_font (char *arg)
     /* [previous][next][first][last][top][bottom][index][help] */
2610 {
2611         return set_get_font (arg,0);
2612 }
2613 
2614 /*
2615  * Load customizable translation table (USER_TRANS[]). All checks are here,
2616  * so we need only include 'return con_set_trans(arg)' in the ioctl handler
2617  * arg points to a 256 byte translation table.
2618  */
2619 int con_set_trans(char * arg)
     /* [previous][next][first][last][top][bottom][index][help] */
2620 {
2621         int i;
2622 
2623         i = verify_area(VERIFY_READ, (void *)arg, E_TABSZ);
2624         if (i)
2625                 return i;
2626 
2627         for (i=0; i<E_TABSZ ; i++) USER_TRANS[i] = get_fs_byte(arg+i);
2628         USER_TRANS[012]=0;
2629         USER_TRANS[014]=0;
2630         USER_TRANS[015]=0;
2631         USER_TRANS[033]=0;
2632         return 0;
2633 }
2634 
2635 int con_get_trans(char * arg)
     /* [previous][next][first][last][top][bottom][index][help] */
2636 {
2637         int i;
2638 
2639         i = verify_area(VERIFY_WRITE, (void *)arg, E_TABSZ);
2640         if (i)
2641                 return i;
2642 
2643         for (i=0; i<E_TABSZ ; i++) put_fs_byte(USER_TRANS[i],arg+i);
2644         return 0;
2645 }

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