root/drivers/char/console.c

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

DEFINITIONS

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

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

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