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. screen_pos
  37. getconsxy
  38. putconsxy
  39. set_mode
  40. setterm_command
  41. insert_char
  42. insert_line
  43. delete_char
  44. delete_line
  45. csi_at
  46. csi_L
  47. csi_P
  48. csi_M
  49. save_cur
  50. restore_cur
  51. reset_terminal
  52. con_stop
  53. con_start
  54. con_write
  55. con_write_room
  56. con_chars_in_buffer
  57. poke_blanked_console
  58. console_print
  59. con_throttle
  60. con_unthrottle
  61. vc_init
  62. con_setsize
  63. con_init
  64. get_scrmem
  65. set_scrmem
  66. do_blank_screen
  67. do_unblank_screen
  68. blank_screen
  69. unblank_screen
  70. update_screen
  71. con_open
  72. set_get_font
  73. set_get_cmap
  74. con_set_cmap
  75. con_get_cmap
  76. reset_palette
  77. set_palette
  78. con_set_font
  79. con_get_font
  80. con_adjust_height

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

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