root/drivers/char/console.c

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

DEFINITIONS

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

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

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