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  *     'unsigned long con_init(unsigned 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].slockstate = 0;
1373         kbd_table[currcons].ledmode = LED_SHOW_FLAGS;
1374         kbd_table[currcons].ledflagstate = kbd_table[currcons].default_ledflagstate;
1375         set_leds();
1376 
1377         default_attr(currcons);
1378         update_attr(currcons);
1379 
1380         tab_stop[0]     = 0x01010100;
1381         tab_stop[1]     =
1382         tab_stop[2]     =
1383         tab_stop[3]     =
1384         tab_stop[4]     = 0x01010101;
1385 
1386         gotoxy(currcons,0,0);
1387         save_cur(currcons);
1388         if (do_clear)
1389             csi_J(currcons,2);
1390 }
1391 
1392 /*
1393  * Turn the Scroll-Lock LED on when the tty is stopped
1394  */
1395 static void con_stop(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
1396 {
1397         int console_num;
1398         if (!tty)
1399                 return;
1400         console_num = MINOR(tty->device) - (tty->driver.minor_start);
1401         if (!vc_cons_allocated(console_num))
1402                 return;
1403         set_vc_kbd_led(kbd_table + console_num, VC_SCROLLOCK);
1404         set_leds();
1405 }
1406 
1407 /*
1408  * Turn the Scroll-Lock LED off when the console is started
1409  */
1410 static void con_start(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
1411 {
1412         int console_num;
1413         if (!tty)
1414                 return;
1415         console_num = MINOR(tty->device) - (tty->driver.minor_start);
1416         if (!vc_cons_allocated(console_num))
1417                 return;
1418         clr_vc_kbd_led(kbd_table + console_num, VC_SCROLLOCK);
1419         set_leds();
1420 }
1421 
1422 static int con_write(struct tty_struct * tty, int from_user,
     /* [previous][next][first][last][top][bottom][index][help] */
1423                      const unsigned char *buf, int count)
1424 {
1425         int c, tc, ok, n = 0;
1426         unsigned int currcons;
1427         struct vt_struct *vt = (struct vt_struct *)tty->driver_data;
1428 
1429         currcons = vt->vc_num;
1430         if (!vc_cons_allocated(currcons)) {
1431             /* could this happen? */
1432             static int error = 0;
1433             if (!error) {
1434                 error = 1;
1435                 printk("con_write: tty %d not allocated\n", currcons+1);
1436             }
1437             return 0;
1438         }
1439 
1440         if (currcons == sel_cons)
1441                 clear_selection();
1442 
1443         disable_bh(KEYBOARD_BH);
1444         while (!tty->stopped && count) {
1445                 c = from_user ? get_user(buf) : *buf;
1446                 buf++; n++; count--;
1447 
1448                 if (utf) {
1449                     /* Combine UTF-8 into Unicode */
1450                     /* Incomplete characters silently ignored */
1451                     if(c > 0x7f) {
1452                         if (utf_count > 0 && (c & 0xc0) == 0x80) {
1453                                 utf_char = (utf_char << 6) | (c & 0x3f);
1454                                 utf_count--;
1455                                 if (utf_count == 0)
1456                                     tc = c = utf_char;
1457                                 else continue;
1458                         } else {
1459                                 if ((c & 0xe0) == 0xc0) {
1460                                     utf_count = 1;
1461                                     utf_char = (c & 0x1f);
1462                                 } else if ((c & 0xf0) == 0xe0) {
1463                                     utf_count = 2;
1464                                     utf_char = (c & 0x0f);
1465                                 } else if ((c & 0xf8) == 0xf0) {
1466                                     utf_count = 3;
1467                                     utf_char = (c & 0x07);
1468                                 } else if ((c & 0xfc) == 0xf8) {
1469                                     utf_count = 4;
1470                                     utf_char = (c & 0x03);
1471                                 } else if ((c & 0xfe) == 0xfc) {
1472                                     utf_count = 5;
1473                                     utf_char = (c & 0x01);
1474                                 } else
1475                                     utf_count = 0;
1476                                 continue;
1477                               }
1478                     } else {
1479                       tc = c;
1480                       utf_count = 0;
1481                     }
1482                 } else {        /* no utf */
1483                   tc = translate[toggle_meta ? (c|0x80) : c];
1484                 }
1485 
1486                 /* If the original code was < 32 we only allow a
1487                  * glyph to be displayed if the code is not normally
1488                  * used (such as for cursor movement) or if the
1489                  * disp_ctrl mode has been explicitly enabled.
1490                  * Note: ESC is *never* allowed to be displayed as
1491                  * that would disable all escape sequences!
1492                  * To display font position 0x1B, go into UTF mode
1493                  * and display character U+F01B, or change the mapping.
1494                  */
1495                 ok = (tc && (c >= 32 || (!utf && !(((disp_ctrl ? CTRL_ALWAYS
1496                                             : CTRL_ACTION) >> c) & 1))));
1497 
1498                 if (vc_state == ESnormal && ok) {
1499                         /* Now try to find out how to display it */
1500                         tc = conv_uni_to_pc(tc);
1501                         if ( tc == -4 )
1502                           {
1503                             /* If we got -4 (not found) then see if we have
1504                                defined a replacement character (U+FFFD) */
1505                             tc = conv_uni_to_pc(0xfffd);
1506                           }
1507                         else if ( tc == -3 )
1508                           {
1509                             /* Bad hash table -- hope for the best */
1510                             tc = c;
1511                           }
1512                         if (tc & ~console_charmask)
1513                           continue; /* Conversion failed */
1514 
1515                         if (need_wrap) {
1516                                 cr(currcons);
1517                                 lf(currcons);
1518                         }
1519                         if (decim)
1520                                 insert_char(currcons);
1521                         scr_writew( video_mode_512ch ?
1522                            ((attr & 0xf7) << 8) + ((tc & 0x100) << 3) +
1523                            (tc & 0x0ff) : (attr << 8) + tc,
1524                            (unsigned short *) pos);
1525                         if (x == video_num_columns - 1)
1526                                 need_wrap = decawm;
1527                         else {
1528                                 x++;
1529                                 pos+=2;
1530                         }
1531                         continue;
1532                 }
1533 
1534                 /*
1535                  *  Control characters can be used in the _middle_
1536                  *  of an escape sequence.
1537                  */
1538                 switch (c) {
1539                         case 7:
1540                                 kd_mksound(0x637, HZ/8);
1541                                 continue;
1542                         case 8:
1543                                 bs(currcons);
1544                                 continue;
1545                         case 9:
1546                                 pos -= (x << 1);
1547                                 while (x < video_num_columns - 1) {
1548                                         x++;
1549                                         if (tab_stop[x >> 5] & (1 << (x & 31)))
1550                                                 break;
1551                                 }
1552                                 pos += (x << 1);
1553                                 continue;
1554                         case 10: case 11: case 12:
1555                                 lf(currcons);
1556                                 if (!is_kbd(lnm))
1557                                         continue;
1558                         case 13:
1559                                 cr(currcons);
1560                                 continue;
1561                         case 14:
1562                                 charset = 1;
1563                                 translate = set_translate(G1_charset);
1564                                 disp_ctrl = 1;
1565                                 continue;
1566                         case 15:
1567                                 charset = 0;
1568                                 translate = set_translate(G0_charset);
1569                                 disp_ctrl = 0;
1570                                 continue;
1571                         case 24: case 26:
1572                                 vc_state = ESnormal;
1573                                 continue;
1574                         case 27:
1575                                 vc_state = ESesc;
1576                                 continue;
1577                         case 127:
1578                                 del(currcons);
1579                                 continue;
1580                         case 128+27:
1581                                 vc_state = ESsquare;
1582                                 continue;
1583                 }
1584                 switch(vc_state) {
1585                         case ESesc:
1586                                 vc_state = ESnormal;
1587                                 switch (c) {
1588                                   case '[':
1589                                         vc_state = ESsquare;
1590                                         continue;
1591                                   case ']':
1592                                         vc_state = ESnonstd;
1593                                         continue;
1594                                   case '%':
1595                                         vc_state = ESpercent;
1596                                         continue;
1597                                   case 'E':
1598                                         cr(currcons);
1599                                         lf(currcons);
1600                                         continue;
1601                                   case 'M':
1602                                         ri(currcons);
1603                                         continue;
1604                                   case 'D':
1605                                         lf(currcons);
1606                                         continue;
1607                                   case 'H':
1608                                         tab_stop[x >> 5] |= (1 << (x & 31));
1609                                         continue;
1610                                   case 'Z':
1611                                         respond_ID(tty);
1612                                         continue;
1613                                   case '7':
1614                                         save_cur(currcons);
1615                                         continue;
1616                                   case '8':
1617                                         restore_cur(currcons);
1618                                         continue;
1619                                   case '(':
1620                                         vc_state = ESsetG0;
1621                                         continue;
1622                                   case ')':
1623                                         vc_state = ESsetG1;
1624                                         continue;
1625                                   case '#':
1626                                         vc_state = EShash;
1627                                         continue;
1628                                   case 'c':
1629                                         reset_terminal(currcons,1);
1630                                         continue;
1631                                   case '>':  /* Numeric keypad */
1632                                         clr_kbd(kbdapplic);
1633                                         continue;
1634                                   case '=':  /* Appl. keypad */
1635                                         set_kbd(kbdapplic);
1636                                         continue;
1637                                 }
1638                                 continue;
1639                         case ESnonstd:
1640                                 if (c=='P') {   /* palette escape sequence */
1641                                         for (npar=0; npar<NPAR; npar++)
1642                                                 par[npar] = 0 ;
1643                                         npar = 0 ;
1644                                         vc_state = ESpalette;
1645                                         continue;
1646                                 } else if (c=='R') {   /* reset palette */
1647                                         reset_palette (currcons);
1648                                         vc_state = ESnormal;
1649                                 } else
1650                                         vc_state = ESnormal;
1651                                 continue;
1652                         case ESpalette:
1653                                 if ( (c>='0'&&c<='9') || (c>='A'&&c<='F') || (c>='a'&&c<='f') ) {
1654                                         par[npar++] = (c>'9' ? (c&0xDF)-'A'+10 : c-'0') ;
1655                                         if (npar==7) {
1656                                                 int i = par[0]*3, j = 1;
1657                                                 palette[i] = 16*par[j++];
1658                                                 palette[i++] += par[j++];
1659                                                 palette[i] = 16*par[j++];
1660                                                 palette[i++] += par[j++];
1661                                                 palette[i] = 16*par[j++];
1662                                                 palette[i] += par[j];
1663                                                 set_palette() ;
1664                                                 vc_state = ESnormal;
1665                                         }
1666                                 } else
1667                                         vc_state = ESnormal;
1668                                 continue;
1669                         case ESsquare:
1670                                 for(npar = 0 ; npar < NPAR ; npar++)
1671                                         par[npar] = 0;
1672                                 npar = 0;
1673                                 vc_state = ESgetpars;
1674                                 if (c == '[') { /* Function key */
1675                                         vc_state=ESfunckey;
1676                                         continue;
1677                                 }
1678                                 ques = (c=='?');
1679                                 if (ques)
1680                                         continue;
1681                         case ESgetpars:
1682                                 if (c==';' && npar<NPAR-1) {
1683                                         npar++;
1684                                         continue;
1685                                 } else if (c>='0' && c<='9') {
1686                                         par[npar] *= 10;
1687                                         par[npar] += c-'0';
1688                                         continue;
1689                                 } else vc_state=ESgotpars;
1690                         case ESgotpars:
1691                                 vc_state = ESnormal;
1692                                 switch(c) {
1693                                         case 'h':
1694                                                 set_mode(currcons,1);
1695                                                 continue;
1696                                         case 'l':
1697                                                 set_mode(currcons,0);
1698                                                 continue;
1699                                         case 'n':
1700                                                 if (!ques)
1701                                                         if (par[0] == 5)
1702                                                                 status_report(tty);
1703                                                         else if (par[0] == 6)
1704                                                                 cursor_report(currcons,tty);
1705                                                 continue;
1706                                 }
1707                                 if (ques) {
1708                                         ques = 0;
1709                                         continue;
1710                                 }
1711                                 switch(c) {
1712                                         case 'G': case '`':
1713                                                 if (par[0]) par[0]--;
1714                                                 gotoxy(currcons,par[0],y);
1715                                                 continue;
1716                                         case 'A':
1717                                                 if (!par[0]) par[0]++;
1718                                                 gotoxy(currcons,x,y-par[0]);
1719                                                 continue;
1720                                         case 'B': case 'e':
1721                                                 if (!par[0]) par[0]++;
1722                                                 gotoxy(currcons,x,y+par[0]);
1723                                                 continue;
1724                                         case 'C': case 'a':
1725                                                 if (!par[0]) par[0]++;
1726                                                 gotoxy(currcons,x+par[0],y);
1727                                                 continue;
1728                                         case 'D':
1729                                                 if (!par[0]) par[0]++;
1730                                                 gotoxy(currcons,x-par[0],y);
1731                                                 continue;
1732                                         case 'E':
1733                                                 if (!par[0]) par[0]++;
1734                                                 gotoxy(currcons,0,y+par[0]);
1735                                                 continue;
1736                                         case 'F':
1737                                                 if (!par[0]) par[0]++;
1738                                                 gotoxy(currcons,0,y-par[0]);
1739                                                 continue;
1740                                         case 'd':
1741                                                 if (par[0]) par[0]--;
1742                                                 gotoxy(currcons,x,par[0]);
1743                                                 continue;
1744                                         case 'H': case 'f':
1745                                                 if (par[0]) par[0]--;
1746                                                 if (par[1]) par[1]--;
1747                                                 gotoxy(currcons,par[1],par[0]);
1748                                                 continue;
1749                                         case 'J':
1750                                                 csi_J(currcons,par[0]);
1751                                                 continue;
1752                                         case 'K':
1753                                                 csi_K(currcons,par[0]);
1754                                                 continue;
1755                                         case 'L':
1756                                                 csi_L(currcons,par[0]);
1757                                                 continue;
1758                                         case 'M':
1759                                                 csi_M(currcons,par[0]);
1760                                                 continue;
1761                                         case 'P':
1762                                                 csi_P(currcons,par[0]);
1763                                                 continue;
1764                                         case 'c':
1765                                                 if (!par[0])
1766                                                         respond_ID(tty);
1767                                                 continue;
1768                                         case 'g':
1769                                                 if (!par[0])
1770                                                         tab_stop[x >> 5] &= ~(1 << (x & 31));
1771                                                 else if (par[0] == 3) {
1772                                                         tab_stop[0] =
1773                                                         tab_stop[1] =
1774                                                         tab_stop[2] =
1775                                                         tab_stop[3] =
1776                                                         tab_stop[4] = 0;
1777                                                 }
1778                                                 continue;
1779                                         case 'm':
1780                                                 csi_m(currcons);
1781                                                 continue;
1782                                         case 'q': /* DECLL - but only 3 leds */
1783                                                 /* map 0,1,2,3 to 0,1,2,4 */
1784                                                 if (par[0] < 4)
1785                                                   setledstate(kbd_table + currcons,
1786                                                               (par[0] < 3) ? par[0] : 4);
1787                                                 continue;
1788                                         case 'r':
1789                                                 if (!par[0])
1790                                                         par[0]++;
1791                                                 if (!par[1])
1792                                                         par[1] = video_num_lines;
1793                                                 /* Minimum allowed region is 2 lines */
1794                                                 if (par[0] < par[1] &&
1795                                                     par[1] <= video_num_lines) {
1796                                                         top=par[0]-1;
1797                                                         bottom=par[1];
1798                                                         gotoxy(currcons,0,0);
1799                                                 }
1800                                                 continue;
1801                                         case 's':
1802                                                 save_cur(currcons);
1803                                                 continue;
1804                                         case 'u':
1805                                                 restore_cur(currcons);
1806                                                 continue;
1807                                         case 'X':
1808                                                 csi_X(currcons, par[0]);
1809                                                 continue;
1810                                         case '@':
1811                                                 csi_at(currcons,par[0]);
1812                                                 continue;
1813                                         case ']': /* setterm functions */
1814                                                 setterm_command(currcons);
1815                                                 continue;
1816                                 }
1817                                 continue;
1818                         case ESpercent:
1819                                 vc_state = ESnormal;
1820                                 switch (c) {
1821                                   case '@':  /* defined in ISO 2022 */
1822                                         utf = 0;
1823                                         continue;
1824                                   case 'G':  /* prelim official escape code */
1825                                   case '8':  /* retained for compatibility */
1826                                         utf = 1;
1827                                         continue;
1828                                 }
1829                                 continue;
1830                         case ESfunckey:
1831                                 vc_state = ESnormal;
1832                                 continue;
1833                         case EShash:
1834                                 vc_state = ESnormal;
1835                                 if (c == '8') {
1836                                         /* DEC screen alignment test. kludge :-) */
1837                                         video_erase_char =
1838                                                 (video_erase_char & 0xff00) | 'E';
1839                                         csi_J(currcons, 2);
1840                                         video_erase_char =
1841                                                 (video_erase_char & 0xff00) | ' ';
1842                                 }
1843                                 continue;
1844                         case ESsetG0:
1845                                 if (c == '0')
1846                                         G0_charset = GRAF_MAP;
1847                                 else if (c == 'B')
1848                                         G0_charset = LAT1_MAP;
1849                                 else if (c == 'U')
1850                                         G0_charset = IBMPC_MAP;
1851                                 else if (c == 'K')
1852                                         G0_charset = USER_MAP;
1853                                 if (charset == 0)
1854                                         translate = set_translate(G0_charset);
1855                                 vc_state = ESnormal;
1856                                 continue;
1857                         case ESsetG1:
1858                                 if (c == '0')
1859                                         G1_charset = GRAF_MAP;
1860                                 else if (c == 'B')
1861                                         G1_charset = LAT1_MAP;
1862                                 else if (c == 'U')
1863                                         G1_charset = IBMPC_MAP;
1864                                 else if (c == 'K')
1865                                         G1_charset = USER_MAP;
1866                                 if (charset == 1)
1867                                         translate = set_translate(G1_charset);
1868                                 vc_state = ESnormal;
1869                                 continue;
1870                         default:
1871                                 vc_state = ESnormal;
1872                 }
1873         }
1874         if (vcmode != KD_GRAPHICS)
1875                 set_cursor(currcons);
1876         enable_bh(KEYBOARD_BH);
1877         return n;
1878 }
1879 
1880 static int con_write_room(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
1881 {
1882         if (tty->stopped)
1883                 return 0;
1884         return 4096;            /* No limit, really; we're not buffering */
1885 }
1886 
1887 static int con_chars_in_buffer(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
1888 {
1889         return 0;               /* we're not buffering */
1890 }
1891 
1892 void poke_blanked_console(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1893 {
1894         timer_active &= ~(1<<BLANK_TIMER);
1895         if (vt_cons[fg_console]->vc_mode == KD_GRAPHICS)
1896                 return;
1897         if (console_blanked) {
1898                 timer_table[BLANK_TIMER].expires = 0;
1899                 timer_active |= 1<<BLANK_TIMER;
1900         } else if (blankinterval) {
1901                 timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
1902                 timer_active |= 1<<BLANK_TIMER;
1903         }
1904 }
1905 
1906 void console_print(const char * b)
     /* [previous][next][first][last][top][bottom][index][help] */
1907 {
1908         int currcons = fg_console;
1909         unsigned char c;
1910         static int printing = 0;
1911 
1912         if (!printable || printing)
1913                 return;  /* console not yet initialized */
1914         printing = 1;
1915 
1916         if (!vc_cons_allocated(currcons)) {
1917                 /* impossible */
1918                 printk("console_print: tty %d not allocated ??\n", currcons+1);
1919                 return;
1920         }
1921 
1922         while ((c = *(b++)) != 0) {
1923                 if (c == 10 || c == 13 || need_wrap) {
1924                         if (c != 13)
1925                                 lf(currcons);
1926                         cr(currcons);
1927                         if (c == 10 || c == 13)
1928                                 continue;
1929                 }
1930                 scr_writew((attr << 8) + c, (unsigned short *) pos);
1931                 if (x == video_num_columns - 1) {
1932                         need_wrap = 1;
1933                         continue;
1934                 }
1935                 x++;
1936                 pos+=2;
1937         }
1938         set_cursor(currcons);
1939         poke_blanked_console();
1940         printing = 0;
1941 }
1942 
1943 /*
1944  * con_throttle and con_unthrottle are only used for
1945  * paste_selection(), which has to stuff in a large number of
1946  * characters...
1947  */
1948 static void con_throttle(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
1949 {
1950 }
1951 
1952 static void con_unthrottle(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
1953 {
1954         struct vt_struct *vt = (struct vt_struct *) tty->driver_data;
1955 
1956         wake_up_interruptible(&vt->paste_wait);
1957 }
1958 
1959 static void vc_init(unsigned int currcons, unsigned long rows, unsigned long cols, int do_clear)
     /* [previous][next][first][last][top][bottom][index][help] */
1960 {
1961         long base = (long) vc_scrbuf[currcons];
1962         int j, k ;
1963 
1964         video_num_columns = cols;
1965         video_num_lines = rows;
1966         video_size_row = cols<<1;
1967         video_screen_size = video_num_lines * video_size_row;
1968 
1969         pos = origin = video_mem_start = base;
1970         scr_end = base + video_screen_size;
1971         video_mem_end = base + video_screen_size;
1972         reset_vc(currcons);
1973         for (j=k=0; j<16; j++) {
1974                 vc_cons[currcons].d->vc_palette[k++] = default_red[j] ;
1975                 vc_cons[currcons].d->vc_palette[k++] = default_grn[j] ;
1976                 vc_cons[currcons].d->vc_palette[k++] = default_blu[j] ;
1977         }
1978         def_color       = 0x07;   /* white */
1979         ulcolor         = 0x0f;   /* bold white */
1980         halfcolor       = 0x08;   /* grey */
1981         vt_cons[currcons]->paste_wait = 0;
1982         reset_terminal(currcons, do_clear);
1983 }
1984 
1985 static void con_setsize(unsigned long rows, unsigned long cols)
     /* [previous][next][first][last][top][bottom][index][help] */
1986 {
1987         video_num_lines = rows;
1988         video_num_columns = cols;
1989         video_size_row = 2 * cols;
1990         video_screen_size = video_num_lines * video_size_row;
1991 }
1992 
1993 /*
1994  *  unsigned long con_init(unsigned long);
1995  *
1996  * This routine initializes console interrupts, and does nothing
1997  * else. If you want the screen to clear, call tty_write with
1998  * the appropriate escape-sequence.
1999  *
2000  * Reads the information preserved by setup.s to determine the current display
2001  * type and sets everything accordingly.
2002  */
2003 unsigned long con_init(unsigned long kmem_start)
     /* [previous][next][first][last][top][bottom][index][help] */
2004 {
2005         const char *display_desc = "????";
2006         int currcons = 0;
2007         int orig_x = ORIG_X;
2008         int orig_y = ORIG_Y;
2009 
2010         memset(&console_driver, 0, sizeof(struct tty_driver));
2011         console_driver.magic = TTY_DRIVER_MAGIC;
2012         console_driver.name = "tty";
2013         console_driver.name_base = 1;
2014         console_driver.major = TTY_MAJOR;
2015         console_driver.minor_start = 1;
2016         console_driver.num = MAX_NR_CONSOLES;
2017         console_driver.type = TTY_DRIVER_TYPE_CONSOLE;
2018         console_driver.init_termios = tty_std_termios;
2019         console_driver.flags = TTY_DRIVER_REAL_RAW;
2020         console_driver.refcount = &console_refcount;
2021         console_driver.table = console_table;
2022         console_driver.termios = console_termios;
2023         console_driver.termios_locked = console_termios_locked;
2024 
2025         console_driver.open = con_open;
2026         console_driver.write = con_write;
2027         console_driver.write_room = con_write_room;
2028         console_driver.chars_in_buffer = con_chars_in_buffer;
2029         console_driver.ioctl = vt_ioctl;
2030         console_driver.stop = con_stop;
2031         console_driver.start = con_start;
2032         console_driver.throttle = con_throttle;
2033         console_driver.unthrottle = con_unthrottle;
2034 
2035         if (tty_register_driver(&console_driver))
2036                 panic("Couldn't register console driver\n");
2037 
2038         con_setsize(ORIG_VIDEO_LINES, ORIG_VIDEO_COLS);
2039         video_page = ORIG_VIDEO_PAGE;                   /* never used */
2040         __scrollback_mode = 0 ;
2041 
2042         timer_table[BLANK_TIMER].fn = blank_screen;
2043         timer_table[BLANK_TIMER].expires = 0;
2044         if (blankinterval) {
2045                 timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
2046                 timer_active |= 1<<BLANK_TIMER;
2047         }
2048 
2049         if (ORIG_VIDEO_MODE == 7)       /* Is this a monochrome display? */
2050         {
2051                 video_mem_base = 0xb0000;
2052                 video_port_reg = 0x3b4;
2053                 video_port_val = 0x3b5;
2054                 if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
2055                 {
2056                         video_type = VIDEO_TYPE_EGAM;
2057                         video_mem_term = 0xb8000;
2058                         display_desc = "EGA+";
2059                         request_region(0x3b0,16,"ega");
2060                 }
2061                 else
2062                 {
2063                         video_type = VIDEO_TYPE_MDA;
2064                         video_mem_term = 0xb2000;
2065                         display_desc = "*MDA";
2066                         request_region(0x3b0,12,"mda");
2067                         request_region(0x3bf, 1,"mda");
2068                 }
2069         }
2070         else                            /* If not, it is color. */
2071         {
2072                 can_do_color = 1;
2073                 video_mem_base = 0xb8000;
2074                 video_port_reg  = 0x3d4;
2075                 video_port_val  = 0x3d5;
2076                 if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
2077                 {
2078                         int i ;
2079 
2080                         video_mem_term = 0xc0000;
2081 
2082                         if (!ORIG_VIDEO_ISVGA) {
2083                                 video_type = VIDEO_TYPE_EGAC;
2084                                 display_desc = "EGA";
2085                                 request_region(0x3c0,32,"ega");
2086                         } else {
2087                                 video_type = VIDEO_TYPE_VGAC;
2088                                 display_desc = "VGA+";
2089                                 request_region(0x3c0,32,"vga+");
2090 
2091 #ifdef VGA_CAN_DO_64KB
2092                                 /*
2093                                  * get 64K rather than 32K of video RAM.
2094                                  * This doesn't actually work on all "VGA"
2095                                  * controllers (it seems like setting MM=01
2096                                  * and COE=1 isn't necessarily a good idea)
2097                                  */
2098                                 video_mem_base = 0xa0000 ;
2099                                 video_mem_term = 0xb0000 ;
2100                                 outb_p (6, 0x3ce) ;
2101                                 outb_p (6, 0x3cf) ;
2102 #endif
2103 
2104                                 /* normalise the palette registers, to point the
2105                                  * 16 screen colours to the first 16 DAC entries */
2106 
2107                                 for (i=0; i<16; i++) {
2108                                         inb_p (0x3da) ;
2109                                         outb_p (i, 0x3c0) ;
2110                                         outb_p (i, 0x3c0) ;
2111                                 }
2112                                 outb_p (0x20, 0x3c0) ;
2113 
2114                                 /* now set the DAC registers back to their default
2115                                  * values */
2116 
2117                                 for (i=0; i<16; i++) {
2118                                         outb_p (color_table[i], 0x3c8) ;
2119                                         outb_p (default_red[i], 0x3c9) ;
2120                                         outb_p (default_grn[i], 0x3c9) ;
2121                                         outb_p (default_blu[i], 0x3c9) ;
2122                                 }
2123                         }
2124                 }
2125                 else
2126                 {
2127                         video_type = VIDEO_TYPE_CGA;
2128                         video_mem_term = 0xba000;
2129                         display_desc = "*CGA";
2130                         request_region(0x3d4,2,"cga");
2131                 }
2132         }
2133 
2134         /* Initialize the variables used for scrolling (mostly EGA/VGA) */
2135 
2136         /* Due to kmalloc roundup allocating statically is more efficient -
2137            so provide MIN_NR_CONSOLES for people with very little memory */
2138         for (currcons = 0; currcons < MIN_NR_CONSOLES; currcons++) {
2139                 int j, k ;
2140 
2141                 vc_cons[currcons].d = (struct vc_data *) kmem_start;
2142                 kmem_start += sizeof(struct vc_data);
2143                 vt_cons[currcons] = (struct vt_struct *) kmem_start;
2144                 kmem_start += sizeof(struct vt_struct);
2145                 vc_scrbuf[currcons] = (unsigned short *) kmem_start;
2146                 kmem_start += video_screen_size;
2147                 kmalloced = 0;
2148                 screenbuf_size = video_screen_size;
2149                 vc_init(currcons, video_num_lines, video_num_columns, currcons);
2150                 for (j=k=0; j<16; j++) {
2151                         vc_cons[currcons].d->vc_palette[k++] = default_red[j] ;
2152                         vc_cons[currcons].d->vc_palette[k++] = default_grn[j] ;
2153                         vc_cons[currcons].d->vc_palette[k++] = default_blu[j] ;
2154                 }
2155         }
2156 
2157         currcons = fg_console = 0;
2158 
2159         video_mem_start = video_mem_base;
2160         video_mem_end = video_mem_term;
2161         origin = video_mem_start;
2162         scr_end = video_mem_start + video_num_lines * video_size_row;
2163         gotoxy(currcons,orig_x,orig_y);
2164         set_origin(currcons);
2165         csi_J(currcons, 0);
2166 
2167         /* Figure out the size of the screen and screen font so we
2168            can figure out the appropriate screen size should we load
2169            a different font */
2170 
2171         printable = 1;
2172         if ( video_type == VIDEO_TYPE_VGAC || video_type == VIDEO_TYPE_EGAC
2173             || video_type == VIDEO_TYPE_EGAM )
2174         {
2175                 default_font_height = video_font_height = ORIG_VIDEO_POINTS;
2176                 /* This may be suboptimal but is a safe bet - go with it */
2177                 video_scan_lines = video_font_height * video_num_lines;
2178 
2179                 printk("Console: %ld point font, %ld scans\n",
2180                        video_font_height, video_scan_lines);
2181         }
2182 
2183         printk("Console: %s %s %ldx%ld, %d virtual console%s (max %d)\n",
2184                 can_do_color ? "colour" : "mono",
2185                 display_desc,
2186                 video_num_columns,video_num_lines,
2187                 MIN_NR_CONSOLES, (MIN_NR_CONSOLES == 1) ? "" : "s", MAX_NR_CONSOLES);
2188         register_console(console_print);
2189         return kmem_start;
2190 }
2191 
2192 static void get_scrmem(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
2193 {
2194         memcpyw((unsigned short *)vc_scrbuf[currcons],
2195                 (unsigned short *)origin, video_screen_size);
2196         __scrollback_mode = 0 ;
2197         origin = video_mem_start = (unsigned long)vc_scrbuf[currcons];
2198         scr_end = video_mem_end = video_mem_start + video_screen_size;
2199         pos = origin + y*video_size_row + (x<<1);
2200 }
2201 
2202 static void set_scrmem(int currcons, long offset)
     /* [previous][next][first][last][top][bottom][index][help] */
2203 {
2204 #ifdef CONFIG_HGA
2205   /* This works with XFree86 1.2, 1.3 and 2.0
2206      This code could be extended and made more generally useful if we could
2207      determine the actual video mode. It appears that this should be
2208      possible on a genuine Hercules card, but I (WM) haven't been able to
2209      read from any of the required registers on my clone card.
2210      */
2211         /* This code should work with Hercules and MDA cards. */
2212         if (video_type == VIDEO_TYPE_MDA)
2213           {
2214             if (vcmode == KD_TEXT)
2215               {
2216                 /* Ensure that the card is in text mode. */
2217                 int     i;
2218                 static char herc_txt_tbl[12] = {
2219                   0x61,0x50,0x52,0x0f,0x19,6,0x19,0x19,2,0x0d,0x0b,0x0c };
2220                 outb_p(0, 0x3bf);  /* Back to power-on defaults */
2221                 outb_p(0, 0x3b8);  /* Blank the screen, select page 0, etc */
2222                 for ( i = 0 ; i < 12 ; i++ )
2223                   {
2224                     outb_p(i, 0x3b4);
2225                     outb_p(herc_txt_tbl[i], 0x3b5);
2226                   }
2227               }
2228 #define HGA_BLINKER_ON 0x20
2229 #define HGA_SCREEN_ON  8
2230             /* Make sure that the hardware is not blanked */
2231             outb_p(HGA_BLINKER_ON | HGA_SCREEN_ON, 0x3b8);
2232           }
2233 #endif CONFIG_HGA
2234 
2235         if (video_mem_term - video_mem_base < offset + video_screen_size)
2236           offset = 0;   /* strange ... */
2237         memcpyw((unsigned short *)(video_mem_base + offset),
2238                 (unsigned short *) origin, video_screen_size);
2239         video_mem_start = video_mem_base;
2240         video_mem_end = video_mem_term;
2241         origin = video_mem_base + offset;
2242         scr_end = origin + video_screen_size;
2243         pos = origin + y*video_size_row + (x<<1);
2244 }
2245 
2246 void do_blank_screen(int nopowersave)
     /* [previous][next][first][last][top][bottom][index][help] */
2247 {
2248         int currcons;
2249 
2250         if (console_blanked)
2251                 return;
2252 
2253         timer_active &= ~(1<<BLANK_TIMER);
2254         timer_table[BLANK_TIMER].fn = unblank_screen;
2255 
2256         /* try not to lose information by blanking, and not to waste memory */
2257         currcons = fg_console;
2258         has_scrolled = 0;
2259         blank__origin = __origin;
2260         blank_origin = origin;
2261         set_origin(fg_console);
2262         get_scrmem(fg_console);
2263         unblank_origin = origin;
2264         memsetw((void *)blank_origin, BLANK,
2265                 2*video_num_lines*video_num_columns);
2266         hide_cursor();
2267         console_blanked = fg_console + 1;
2268 
2269         if(!nopowersave)
2270             vesa_blank();
2271 }
2272 
2273 void do_unblank_screen(void)
     /* [previous][next][first][last][top][bottom][index][help] */
2274 {
2275         int currcons;
2276         int resetorg;
2277         long offset;
2278 
2279         if (!console_blanked)
2280                 return;
2281         if (!vc_cons_allocated(fg_console)) {
2282                 /* impossible */
2283                 printk("unblank_screen: tty %d not allocated ??\n", fg_console+1);
2284                 return;
2285         }
2286         timer_table[BLANK_TIMER].fn = blank_screen;
2287         if (blankinterval) {
2288                 timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
2289                 timer_active |= 1<<BLANK_TIMER;
2290         }
2291 
2292         currcons = fg_console;
2293         offset = 0;
2294         resetorg = 0;
2295         if (console_blanked == fg_console + 1 && origin == unblank_origin
2296             && !has_scrolled) {
2297                 /* try to restore the exact situation before blanking */
2298                 resetorg = 1;
2299                 offset = (blank_origin - video_mem_base)
2300                         - (unblank_origin - video_mem_start);
2301         }
2302 
2303         console_blanked = 0;
2304         set_scrmem(fg_console, offset);
2305         set_origin(fg_console);
2306         set_cursor(fg_console);
2307         if (resetorg)
2308                 __set_origin(blank__origin);
2309 
2310         vesa_unblank();
2311 }
2312 
2313 /*
2314  * If a blank_screen is due to a timer, then a power save is allowed.
2315  * If it is related to console_switching, then avoid vesa_blank().
2316  */
2317 static void blank_screen(void)
     /* [previous][next][first][last][top][bottom][index][help] */
2318 {
2319         do_blank_screen(0);
2320 }
2321 
2322 static void unblank_screen(void)
     /* [previous][next][first][last][top][bottom][index][help] */
2323 {
2324         do_unblank_screen();
2325 }
2326 
2327 void update_screen(int new_console)
     /* [previous][next][first][last][top][bottom][index][help] */
2328 {
2329         static int lock = 0;
2330 
2331         if (new_console == fg_console || lock)
2332                 return;
2333         if (!vc_cons_allocated(new_console)) {
2334                 /* strange ... */
2335                 printk("update_screen: tty %d not allocated ??\n", new_console+1);
2336                 return;
2337         }
2338         lock = 1;
2339 
2340         clear_selection();
2341 
2342         if (!console_blanked)
2343                 get_scrmem(fg_console);
2344         else
2345                 console_blanked = -1;      /* no longer of the form console+1 */
2346         fg_console = new_console; /* this is the only (nonzero) assignment to fg_console */
2347                                   /* consequently, fg_console will always be allocated */
2348         set_scrmem(fg_console, 0);
2349         set_origin(fg_console);
2350         set_cursor(fg_console);
2351         set_leds();
2352         compute_shiftstate();
2353         lock = 0;
2354 }
2355 
2356 /*
2357  * Allocate the console screen memory.
2358  */
2359 int con_open(struct tty_struct *tty, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
2360 {
2361         unsigned int    idx;
2362         int i;
2363 
2364         idx = MINOR(tty->device) - tty->driver.minor_start;
2365 
2366         i = vc_allocate(idx);
2367         if (i)
2368                 return i;
2369 
2370         vt_cons[idx]->vc_num = idx;
2371         tty->driver_data = vt_cons[idx];
2372 
2373         if (!tty->winsize.ws_row && !tty->winsize.ws_col) {
2374                 tty->winsize.ws_row = video_num_lines;
2375                 tty->winsize.ws_col = video_num_columns;
2376         }
2377         return 0;
2378 }
2379 
2380 
2381 /*
2382  * PIO_FONT support.
2383  *
2384  * The font loading code goes back to the codepage package by
2385  * Joel Hoffman (joel@wam.umd.edu). (He reports that the original
2386  * reference is: "From: p. 307 of _Programmer's Guide to PC & PS/2
2387  * Video Systems_ by Richard Wilton. 1987.  Microsoft Press".)
2388  *
2389  * Change for certain monochrome monitors by Yury Shevchuck
2390  * (sizif@botik.yaroslavl.su).
2391  */
2392 
2393 #define colourmap ((char *)0xa0000)
2394 /* Pauline Middelink <middelin@polyware.iaf.nl> reports that we
2395    should use 0xA0000 for the bwmap as well.. */
2396 #define blackwmap ((char *)0xa0000)
2397 #define cmapsz 8192
2398 #define attrib_port (0x3c0)
2399 #define seq_port_reg (0x3c4)
2400 #define seq_port_val (0x3c5)
2401 #define gr_port_reg (0x3ce)
2402 #define gr_port_val (0x3cf)
2403 
2404 static int set_get_font(char * arg, int set, int ch512)
     /* [previous][next][first][last][top][bottom][index][help] */
2405 {
2406 #ifdef CAN_LOAD_EGA_FONTS
2407         int i;
2408         char *charmap;
2409         int beg;
2410         unsigned short video_port_status = video_port_reg + 6;
2411         int font_select = 0x00;
2412 
2413         /* no use to "load" CGA... */
2414 
2415         if (video_type == VIDEO_TYPE_EGAC || video_type == VIDEO_TYPE_VGAC) {
2416                 charmap = colourmap;
2417                 beg = 0x0e;
2418 #ifdef VGA_CAN_DO_64KB
2419                 if (video_type == VIDEO_TYPE_VGAC)
2420                         beg = 0x06;
2421 #endif
2422         } else if (video_type == VIDEO_TYPE_EGAM) {
2423                 charmap = blackwmap;
2424                 beg = 0x0a;
2425         } else
2426                 return -EINVAL;
2427         
2428         if (arg)
2429           {
2430             i = verify_area(set ? VERIFY_READ : VERIFY_WRITE, (void *)arg,
2431                             ch512 ? 2*cmapsz : cmapsz);
2432             if (i)
2433               return i;
2434           }
2435         else
2436           ch512 = 0;            /* Default font is always 256 */
2437 
2438 #ifdef BROKEN_GRAPHICS_PROGRAMS
2439         /*
2440          * All fonts are loaded in slot 0 (0:1 for 512 ch)
2441          */
2442 
2443         if (!arg)
2444           return -EINVAL;       /* Return to default font not supported */
2445 
2446         video_font_is_default = 0;
2447         font_select = ch512 ? 0x04 : 0x00;
2448 #else   
2449         /*
2450          * The default font is kept in slot 0 and is never touched.
2451          * A custom font is loaded in slot 2 (256 ch) or 2:3 (512 ch)
2452          */
2453 
2454         if (set)
2455           {
2456             video_font_is_default = !arg;
2457             font_select = arg ? (ch512 ? 0x0e : 0x0a) : 0x00;
2458           }
2459 
2460         if ( !video_font_is_default )
2461           charmap += 4*cmapsz;
2462 #endif
2463 
2464         cli();
2465         outb_p( 0x00, seq_port_reg );   /* First, the sequencer */
2466         outb_p( 0x01, seq_port_val );   /* Synchronous reset */
2467         outb_p( 0x02, seq_port_reg );
2468         outb_p( 0x04, seq_port_val );   /* CPU writes only to map 2 */
2469         outb_p( 0x04, seq_port_reg );
2470         outb_p( 0x07, seq_port_val );   /* Sequential addressing */
2471         outb_p( 0x00, seq_port_reg );
2472         outb_p( 0x03, seq_port_val );   /* Clear synchronous reset */
2473 
2474         outb_p( 0x04, gr_port_reg );    /* Now, the graphics controller */
2475         outb_p( 0x02, gr_port_val );    /* select map 2 */
2476         outb_p( 0x05, gr_port_reg );
2477         outb_p( 0x00, gr_port_val );    /* disable odd-even addressing */
2478         outb_p( 0x06, gr_port_reg );
2479         outb_p( 0x00, gr_port_val );    /* map start at A000:0000 */
2480         sti();
2481         
2482         if (arg)
2483           {
2484             if (set)
2485               for (i=0; i<cmapsz ; i++)
2486                 scr_writeb(get_user(arg + i), charmap + i);
2487             else
2488               for (i=0; i<cmapsz ; i++)
2489                 put_user(scr_readb(charmap + i), arg + i);
2490             
2491             
2492         /*
2493          * In 512-character mode, the character map is not contiguous if
2494          * we want to remain EGA compatible -- which we do
2495          */
2496 
2497             if (ch512)
2498               {
2499                 charmap += 2*cmapsz;
2500                 arg += cmapsz;
2501                 if (set)
2502                   for (i=0; i<cmapsz ; i++)
2503                     *(charmap+i) = get_user(arg+i);
2504                 else
2505                   for (i=0; i<cmapsz ; i++)
2506                     put_user(*(charmap+i), arg+i);
2507               }
2508           }
2509         
2510         cli();
2511         outb_p( 0x00, seq_port_reg );   /* First, the sequencer */
2512         outb_p( 0x01, seq_port_val );   /* Synchronous reset */
2513         outb_p( 0x02, seq_port_reg );
2514         outb_p( 0x03, seq_port_val );   /* CPU writes to maps 0 and 1 */
2515         outb_p( 0x04, seq_port_reg );
2516         outb_p( 0x03, seq_port_val );   /* odd-even addressing */
2517         if (set)
2518           {
2519             outb_p( 0x03, seq_port_reg ); /* Character Map Select */
2520             outb_p( font_select, seq_port_val );
2521           }
2522         outb_p( 0x00, seq_port_reg );
2523         outb_p( 0x03, seq_port_val );   /* clear synchronous reset */
2524 
2525         outb_p( 0x04, gr_port_reg );    /* Now, the graphics controller */
2526         outb_p( 0x00, gr_port_val );    /* select map 0 for CPU */
2527         outb_p( 0x05, gr_port_reg );
2528         outb_p( 0x10, gr_port_val );    /* enable even-odd addressing */
2529         outb_p( 0x06, gr_port_reg );
2530         outb_p( beg, gr_port_val );     /* map starts at b800:0 or b000:0 */
2531         if (set)                        /* attribute controller */
2532           {
2533             /* 256-char: enable intensity bit
2534                512-char: disable intensity bit */
2535             inb_p( video_port_status ); /* clear address flip-flop */
2536             outb_p ( 0x12, attrib_port ); /* color plane enable register */
2537             outb_p ( ch512 ? 0x07 : 0x0f, attrib_port );
2538             /* Wilton (1987) mentions the following; I don't know what
2539                it means, but it works, and it appears necessary */
2540             inb_p( video_port_status );
2541             outb_p ( 0x20, attrib_port );
2542           }
2543         sti();
2544 
2545         return 0;
2546 #else
2547         return -EINVAL;
2548 #endif
2549 }
2550 
2551 #define dac_reg (0x3c8)
2552 #define dac_val (0x3c9)
2553 
2554 static int set_get_cmap(unsigned char * arg, int set) {
     /* [previous][next][first][last][top][bottom][index][help] */
2555 #ifdef CAN_LOAD_PALETTE
2556         int i;
2557 
2558         /* no use to set colourmaps in less than colour VGA */
2559 
2560         if (video_type != VIDEO_TYPE_VGAC)
2561                 return -EINVAL;
2562 
2563         i = verify_area(set ? VERIFY_READ : VERIFY_WRITE, (void *)arg, 16*3);
2564         if (i)
2565                 return i;
2566 
2567         for (i=0; i<16; i++) {
2568                 if (set) {
2569                         default_red[i] = get_user(arg++) ;
2570                         default_grn[i] = get_user(arg++) ;
2571                         default_blu[i] = get_user(arg++) ;
2572                 } else {
2573                         put_user (default_red[i], arg++) ;
2574                         put_user (default_grn[i], arg++) ;
2575                         put_user (default_blu[i], arg++) ;
2576                 }
2577         }
2578         if (set) {
2579                 for (i=0; i<MAX_NR_CONSOLES; i++)
2580                         if (vc_cons_allocated(i)) {
2581                                 int j, k ;
2582                                 for (j=k=0; j<16; j++) {
2583                                         vc_cons[i].d->vc_palette[k++] = default_red[j];
2584                                         vc_cons[i].d->vc_palette[k++] = default_grn[j];
2585                                         vc_cons[i].d->vc_palette[k++] = default_blu[j];
2586                                 }
2587                         }
2588                 set_palette() ;
2589         }
2590 
2591         return 0;
2592 #else
2593         return -EINVAL;
2594 #endif
2595 }
2596 
2597 /*
2598  * Load palette into the EGA/VGA DAC registers. arg points to a colour
2599  * map, 3 bytes per colour, 16 colours, range from 0 to 255.
2600  */
2601 
2602 int con_set_cmap (unsigned char *arg)
     /* [previous][next][first][last][top][bottom][index][help] */
2603 {
2604         return set_get_cmap (arg,1);
2605 }
2606 
2607 int con_get_cmap (unsigned char *arg)
     /* [previous][next][first][last][top][bottom][index][help] */
2608 {
2609         return set_get_cmap (arg,0);
2610 }
2611 
2612 void reset_palette (int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
2613 {
2614         int j, k ;
2615         for (j=k=0; j<16; j++) {
2616                 palette[k++] = default_red[j];
2617                 palette[k++] = default_grn[j];
2618                 palette[k++] = default_blu[j];
2619         }
2620         set_palette() ;
2621 }
2622 
2623 void set_palette (void)
     /* [previous][next][first][last][top][bottom][index][help] */
2624 {
2625         int i, j ;
2626 
2627         if (video_type != VIDEO_TYPE_VGAC || console_blanked ||
2628             vt_cons[fg_console]->vc_mode == KD_GRAPHICS)
2629                 return ;
2630 
2631         for (i=j=0; i<16; i++) {
2632                 outb_p (color_table[i], dac_reg) ;
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                 outb_p (vc_cons[fg_console].d->vc_palette[j++]>>2, dac_val) ;
2636         }
2637 }
2638 
2639 /*
2640  * Load font into the EGA/VGA character generator. arg points to a 8192
2641  * byte map, 32 bytes per character. Only first H of them are used for
2642  * 8xH fonts (0 < H <= 32).
2643  */
2644 
2645 int con_set_font (char *arg, int ch512)
     /* [previous][next][first][last][top][bottom][index][help] */
2646 {
2647         int i;
2648 
2649         i = set_get_font (arg,1,ch512);
2650         if ( !i ) {
2651                 hashtable_contents_valid = 0;
2652                 video_mode_512ch = ch512;
2653                 console_charmask = ch512 ? 0x1ff : 0x0ff;
2654         }
2655         return i;
2656 }
2657 
2658 int con_get_font (char *arg)
     /* [previous][next][first][last][top][bottom][index][help] */
2659 {
2660         return set_get_font (arg,0,video_mode_512ch);
2661 }
2662 
2663 /*
2664  * Adjust the screen to fit a font of a certain height
2665  *
2666  * Returns < 0 for error, 0 if nothing changed, and the number
2667  * of lines on the adjusted console if changed.
2668  */
2669 int con_adjust_height(unsigned long fontheight)
     /* [previous][next][first][last][top][bottom][index][help] */
2670 {
2671         int rows, maxscan;
2672         unsigned char ovr, vde, fsr, curs, cure;
2673 
2674         if (fontheight > 32 || (video_type != VIDEO_TYPE_VGAC &&
2675             video_type != VIDEO_TYPE_EGAC && video_type != VIDEO_TYPE_EGAM))
2676                 return -EINVAL;
2677 
2678         if ( fontheight == video_font_height || fontheight == 0 )
2679                 return 0;
2680 
2681         video_font_height = fontheight;
2682 
2683         rows = video_scan_lines/fontheight;     /* Number of video rows we end up with */
2684         maxscan = rows*fontheight - 1;          /* Scan lines to actually display-1 */
2685 
2686         /* Reprogram the CRTC for the new font size
2687            Note: the attempt to read the overflow register will fail
2688            on an EGA, but using 0xff for the previous value appears to
2689            be OK for EGA text modes in the range 257-512 scan lines, so I
2690            guess we don't need to worry about it.
2691 
2692            The same applies for the spill bits in the font size and cursor
2693            registers; they are write-only on EGA, but it appears that they
2694            are all don't care bits on EGA, so I guess it doesn't matter. */
2695 
2696         cli();
2697         outb_p( 0x07, video_port_reg );         /* CRTC overflow register */
2698         ovr = inb_p(video_port_val);
2699         outb_p( 0x09, video_port_reg );         /* Font size register */
2700         fsr = inb_p(video_port_val);
2701         outb_p( 0x0a, video_port_reg );         /* Cursor start */
2702         curs = inb_p(video_port_val);
2703         outb_p( 0x0b, video_port_reg );         /* Cursor end */
2704         cure = inb_p(video_port_val);
2705         sti();
2706 
2707         vde = maxscan & 0xff;                   /* Vertical display end reg */
2708         ovr = (ovr & 0xbd) +                    /* Overflow register */
2709               ((maxscan & 0x100) >> 7) +
2710               ((maxscan & 0x200) >> 3);
2711         fsr = (fsr & 0xe0) + (fontheight-1);    /*  Font size register */
2712         curs = (curs & 0xc0) + fontheight - (fontheight < 10 ? 2 : 3);
2713         cure = (cure & 0xe0) + fontheight - (fontheight < 10 ? 1 : 2);
2714 
2715         cli();
2716         outb_p( 0x07, video_port_reg );         /* CRTC overflow register */
2717         outb_p( ovr, video_port_val );
2718         outb_p( 0x09, video_port_reg );         /* Font size */
2719         outb_p( fsr, video_port_val );
2720         outb_p( 0x0a, video_port_reg );         /* Cursor start */
2721         outb_p( curs, video_port_val );
2722         outb_p( 0x0b, video_port_reg );         /* Cursor end */
2723         outb_p( cure, video_port_val );
2724         outb_p( 0x12, video_port_reg );         /* Vertical display limit */
2725         outb_p( vde, video_port_val );
2726         sti();
2727 
2728         if ( rows == video_num_lines ) {
2729           /* Change didn't affect number of lines -- no need to scare
2730              the rest of the world */
2731           return 0;
2732         }
2733 
2734         vc_resize(rows, 0);                     /* Adjust console size */
2735 
2736         return rows;
2737 }

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