root/drivers/char/console.c

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

DEFINITIONS

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

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

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