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

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