root/drivers/char/console.c

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

DEFINITIONS

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

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

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