root/drivers/char/console.c

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

DEFINITIONS

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

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

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