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,16,"mda");
2055                 }
2056         }
2057         else                            /* If not, it is color. */
2058         {
2059                 can_do_color = 1;
2060                 video_mem_base = 0xb8000;
2061                 video_port_reg  = 0x3d4;
2062                 video_port_val  = 0x3d5;
2063                 if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
2064                 {
2065                         int i ;
2066 
2067                         video_mem_term = 0xc0000;
2068 
2069                         if (!ORIG_VIDEO_ISVGA) {
2070                                 video_type = VIDEO_TYPE_EGAC;
2071                                 display_desc = "EGA";
2072                                 request_region(0x3c0,32,"ega");
2073                         } else {
2074                                 video_type = VIDEO_TYPE_VGAC;
2075                                 display_desc = "VGA+";
2076                                 request_region(0x3c0,32,"vga+");
2077 
2078 #ifdef VGA_CAN_DO_64KB
2079                                 /*
2080                                  * get 64K rather than 32K of video RAM.
2081                                  * This doesn't actually work on all "VGA"
2082                                  * controllers (it seems like setting MM=01
2083                                  * and COE=1 isn't necessarily a good idea)
2084                                  */
2085                                 video_mem_base = 0xa0000 ;
2086                                 video_mem_term = 0xb0000 ;
2087                                 outb_p (6, 0x3ce) ;
2088                                 outb_p (6, 0x3cf) ;
2089 #endif
2090 
2091                                 /* normalise the palette registers, to point the
2092                                  * 16 screen colours to the first 16 DAC entries */
2093 
2094                                 for (i=0; i<16; i++) {
2095                                         inb_p (0x3da) ;
2096                                         outb_p (i, 0x3c0) ;
2097                                         outb_p (i, 0x3c0) ;
2098                                 }
2099                                 outb_p (0x20, 0x3c0) ;
2100 
2101                                 /* now set the DAC registers back to their default
2102                                  * values */
2103 
2104                                 for (i=0; i<16; i++) {
2105                                         outb_p (color_table[i], 0x3c8) ;
2106                                         outb_p (default_red[i], 0x3c9) ;
2107                                         outb_p (default_grn[i], 0x3c9) ;
2108                                         outb_p (default_blu[i], 0x3c9) ;
2109                                 }
2110                         }
2111                 }
2112                 else
2113                 {
2114                         video_type = VIDEO_TYPE_CGA;
2115                         video_mem_term = 0xba000;
2116                         display_desc = "*CGA";
2117                         request_region(0x3d4,2,"cga");
2118                 }
2119         }
2120 
2121         /* Initialize the variables used for scrolling (mostly EGA/VGA) */
2122 
2123         /* Due to kmalloc roundup allocating statically is more efficient -
2124            so provide MIN_NR_CONSOLES for people with very little memory */
2125         for (currcons = 0; currcons < MIN_NR_CONSOLES; currcons++) {
2126                 int j, k ;
2127 
2128                 vc_cons[currcons].d = (struct vc_data *) kmem_start;
2129                 kmem_start += sizeof(struct vc_data);
2130                 vt_cons[currcons] = (struct vt_struct *) kmem_start;
2131                 kmem_start += sizeof(struct vt_struct);
2132                 vc_scrbuf[currcons] = (unsigned short *) kmem_start;
2133                 kmem_start += video_screen_size;
2134                 kmalloced = 0;
2135                 screenbuf_size = video_screen_size;
2136                 vc_init(currcons, video_num_lines, video_num_columns, currcons);
2137                 for (j=k=0; j<16; j++) {
2138                         vc_cons[currcons].d->vc_palette[k++] = default_red[j] ;
2139                         vc_cons[currcons].d->vc_palette[k++] = default_grn[j] ;
2140                         vc_cons[currcons].d->vc_palette[k++] = default_blu[j] ;
2141                 }
2142         }
2143 
2144         currcons = fg_console = 0;
2145 
2146         video_mem_start = video_mem_base;
2147         video_mem_end = video_mem_term;
2148         origin = video_mem_start;
2149         scr_end = video_mem_start + video_num_lines * video_size_row;
2150         gotoxy(currcons,orig_x,orig_y);
2151         set_origin(currcons);
2152         csi_J(currcons, 0);
2153 
2154 
2155         /* Figure out the size of the screen and screen font so we
2156            can figure out the appropriate screen size should we load
2157            a different font */
2158 
2159         printable = 1;
2160         if ( video_type == VIDEO_TYPE_VGAC || video_type == VIDEO_TYPE_EGAC
2161             || video_type == VIDEO_TYPE_EGAM )
2162         {
2163                 video_font_height = ORIG_VIDEO_POINTS;
2164                 /* This may be suboptimal but is a safe bet - go with it */
2165                 video_scan_lines = video_font_height * video_num_lines;
2166                 printk("Console: %ld point font, %ld scans\n",
2167                        video_font_height, video_scan_lines);
2168         }
2169 
2170         printk("Console: %s %s %ldx%ld, %d virtual console%s (max %d)\n",
2171                 can_do_color ? "colour" : "mono",
2172                 display_desc,
2173                 video_num_columns,video_num_lines,
2174                 MIN_NR_CONSOLES, (MIN_NR_CONSOLES == 1) ? "" : "s", MAX_NR_CONSOLES);
2175         register_console(console_print);
2176         return kmem_start;
2177 }
2178 
2179 static void get_scrmem(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
2180 {
2181         memcpyw((unsigned short *)vc_scrbuf[currcons],
2182                 (unsigned short *)origin, video_screen_size);
2183         __scrollback_mode = 0 ;
2184         origin = video_mem_start = (unsigned long)vc_scrbuf[currcons];
2185         scr_end = video_mem_end = video_mem_start + video_screen_size;
2186         pos = origin + y*video_size_row + (x<<1);
2187 }
2188 
2189 static void set_scrmem(int currcons, long offset)
     /* [previous][next][first][last][top][bottom][index][help] */
2190 {
2191 #ifdef CONFIG_HGA
2192   /* This works with XFree86 1.2, 1.3 and 2.0
2193      This code could be extended and made more generally useful if we could
2194      determine the actual video mode. It appears that this should be
2195      possible on a genuine Hercules card, but I (WM) haven't been able to
2196      read from any of the required registers on my clone card.
2197      */
2198         /* This code should work with Hercules and MDA cards. */
2199         if (video_type == VIDEO_TYPE_MDA)
2200           {
2201             if (vcmode == KD_TEXT)
2202               {
2203                 /* Ensure that the card is in text mode. */
2204                 int     i;
2205                 static char herc_txt_tbl[12] = {
2206                   0x61,0x50,0x52,0x0f,0x19,6,0x19,0x19,2,0x0d,0x0b,0x0c };
2207                 outb_p(0, 0x3bf);  /* Back to power-on defaults */
2208                 outb_p(0, 0x3b8);  /* Blank the screen, select page 0, etc */
2209                 for ( i = 0 ; i < 12 ; i++ )
2210                   {
2211                     outb_p(i, 0x3b4);
2212                     outb_p(herc_txt_tbl[i], 0x3b5);
2213                   }
2214               }
2215 #define HGA_BLINKER_ON 0x20
2216 #define HGA_SCREEN_ON  8
2217             /* Make sure that the hardware is not blanked */
2218             outb_p(HGA_BLINKER_ON | HGA_SCREEN_ON, 0x3b8);
2219           }
2220 #endif CONFIG_HGA
2221 
2222         if (video_mem_term - video_mem_base < offset + video_screen_size)
2223           offset = 0;   /* strange ... */
2224         memcpyw((unsigned short *)(video_mem_base + offset),
2225                 (unsigned short *) origin, video_screen_size);
2226         video_mem_start = video_mem_base;
2227         video_mem_end = video_mem_term;
2228         origin = video_mem_base + offset;
2229         scr_end = origin + video_screen_size;
2230         pos = origin + y*video_size_row + (x<<1);
2231 }
2232 
2233 void do_blank_screen(int nopowersave)
     /* [previous][next][first][last][top][bottom][index][help] */
2234 {
2235         int currcons;
2236 
2237         if (console_blanked)
2238                 return;
2239 
2240         timer_active &= ~(1<<BLANK_TIMER);
2241         timer_table[BLANK_TIMER].fn = unblank_screen;
2242 
2243         /* try not to lose information by blanking, and not to waste memory */
2244         currcons = fg_console;
2245         has_scrolled = 0;
2246         blank__origin = __origin;
2247         blank_origin = origin;
2248         set_origin(fg_console);
2249         get_scrmem(fg_console);
2250         unblank_origin = origin;
2251         memsetw((void *)blank_origin, BLANK,
2252                 2*video_num_lines*video_num_columns);
2253         hide_cursor();
2254         console_blanked = fg_console + 1;
2255 
2256         if(!nopowersave)
2257             vesa_blank();
2258 }
2259 
2260 void do_unblank_screen(void)
     /* [previous][next][first][last][top][bottom][index][help] */
2261 {
2262         int currcons;
2263         int resetorg;
2264         long offset;
2265 
2266         if (!console_blanked)
2267                 return;
2268         if (!vc_cons_allocated(fg_console)) {
2269                 /* impossible */
2270                 printk("unblank_screen: tty %d not allocated ??\n", fg_console+1);
2271                 return;
2272         }
2273         timer_table[BLANK_TIMER].fn = blank_screen;
2274         if (blankinterval) {
2275                 timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
2276                 timer_active |= 1<<BLANK_TIMER;
2277         }
2278 
2279         currcons = fg_console;
2280         offset = 0;
2281         resetorg = 0;
2282         if (console_blanked == fg_console + 1 && origin == unblank_origin
2283             && !has_scrolled) {
2284                 /* try to restore the exact situation before blanking */
2285                 resetorg = 1;
2286                 offset = (blank_origin - video_mem_base)
2287                         - (unblank_origin - video_mem_start);
2288         }
2289 
2290         console_blanked = 0;
2291         set_scrmem(fg_console, offset);
2292         set_origin(fg_console);
2293         set_cursor(fg_console);
2294         if (resetorg)
2295                 __set_origin(blank__origin);
2296 
2297         vesa_unblank();
2298 }
2299 
2300 /*
2301  * If a blank_screen is due to a timer, then a power save is allowed.
2302  * If it is related to console_switching, then avoid vesa_blank().
2303  */
2304 static void blank_screen(void)
     /* [previous][next][first][last][top][bottom][index][help] */
2305 {
2306         do_blank_screen(0);
2307 }
2308 
2309 static void unblank_screen(void)
     /* [previous][next][first][last][top][bottom][index][help] */
2310 {
2311         do_unblank_screen();
2312 }
2313 
2314 void update_screen(int new_console)
     /* [previous][next][first][last][top][bottom][index][help] */
2315 {
2316         static int lock = 0;
2317 
2318         if (new_console == fg_console || lock)
2319                 return;
2320         if (!vc_cons_allocated(new_console)) {
2321                 /* strange ... */
2322                 printk("update_screen: tty %d not allocated ??\n", new_console+1);
2323                 return;
2324         }
2325         lock = 1;
2326 
2327         clear_selection();
2328 
2329         if (!console_blanked)
2330                 get_scrmem(fg_console);
2331         else
2332                 console_blanked = -1;      /* no longer of the form console+1 */
2333         fg_console = new_console; /* this is the only (nonzero) assignment to fg_console */
2334                                   /* consequently, fg_console will always be allocated */
2335         set_scrmem(fg_console, 0);
2336         set_origin(fg_console);
2337         set_cursor(fg_console);
2338         set_leds();
2339         compute_shiftstate();
2340         lock = 0;
2341 }
2342 
2343 /*
2344  * Allocate the console screen memory.
2345  */
2346 int con_open(struct tty_struct *tty, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
2347 {
2348         unsigned int    idx;
2349         int i;
2350 
2351         idx = MINOR(tty->device) - tty->driver.minor_start;
2352 
2353         i = vc_allocate(idx);
2354         if (i)
2355                 return i;
2356 
2357         vt_cons[idx]->vc_num = idx;
2358         tty->driver_data = vt_cons[idx];
2359 
2360         if (!tty->winsize.ws_row && !tty->winsize.ws_col) {
2361                 tty->winsize.ws_row = video_num_lines;
2362                 tty->winsize.ws_col = video_num_columns;
2363         }
2364         return 0;
2365 }
2366 
2367 
2368 /*
2369  * PIO_FONT support.
2370  *
2371  * The font loading code goes back to the codepage package by
2372  * Joel Hoffman (joel@wam.umd.edu). (He reports that the original
2373  * reference is: "From: p. 307 of _Programmer's Guide to PC & PS/2
2374  * Video Systems_ by Richard Wilton. 1987.  Microsoft Press".)
2375  *
2376  * Change for certain monochrome monitors by Yury Shevchuck
2377  * (sizif@botik.yaroslavl.su).
2378  */
2379 
2380 #define colourmap ((char *)0xa0000)
2381 /* Pauline Middelink <middelin@polyware.iaf.nl> reports that we
2382    should use 0xA0000 for the bwmap as well.. */
2383 #define blackwmap ((char *)0xa0000)
2384 #define cmapsz 8192
2385 #define attrib_port (0x3c0)
2386 #define seq_port_reg (0x3c4)
2387 #define seq_port_val (0x3c5)
2388 #define gr_port_reg (0x3ce)
2389 #define gr_port_val (0x3cf)
2390 
2391 static int set_get_font(char * arg, int set, int ch512)
     /* [previous][next][first][last][top][bottom][index][help] */
2392 {
2393 #ifdef CAN_LOAD_EGA_FONTS
2394         int i;
2395         char *charmap;
2396         int beg;
2397         unsigned short video_port_status = video_port_reg + 6;
2398 
2399         /* no use to "load" CGA... */
2400 
2401         if (video_type == VIDEO_TYPE_EGAC || video_type == VIDEO_TYPE_VGAC) {
2402                 charmap = colourmap;
2403                 beg = 0x0e;
2404 #ifdef VGA_CAN_DO_64KB
2405                 if (video_type == VIDEO_TYPE_VGAC)
2406                         beg = 0x06;
2407 #endif
2408         } else if (video_type == VIDEO_TYPE_EGAM) {
2409                 charmap = blackwmap;
2410                 beg = 0x0a;
2411         } else
2412                 return -EINVAL;
2413 
2414         i = verify_area(set ? VERIFY_READ : VERIFY_WRITE, (void *)arg,
2415                         ch512 ? 2*cmapsz : cmapsz);
2416         if (i)
2417                 return i;
2418 
2419         cli();
2420         outb_p( 0x00, seq_port_reg );   /* First, the sequencer */
2421         outb_p( 0x01, seq_port_val );   /* Synchronous reset */
2422         outb_p( 0x02, seq_port_reg );
2423         outb_p( 0x04, seq_port_val );   /* CPU writes only to map 2 */
2424         outb_p( 0x04, seq_port_reg );
2425         outb_p( 0x07, seq_port_val );   /* Sequential addressing */
2426         outb_p( 0x00, seq_port_reg );
2427         outb_p( 0x03, seq_port_val );   /* Clear synchronous reset */
2428 
2429         outb_p( 0x04, gr_port_reg );    /* Now, the graphics controller */
2430         outb_p( 0x02, gr_port_val );    /* select map 2 */
2431         outb_p( 0x05, gr_port_reg );
2432         outb_p( 0x00, gr_port_val );    /* disable odd-even addressing */
2433         outb_p( 0x06, gr_port_reg );
2434         outb_p( 0x00, gr_port_val );    /* map start at A000:0000 */
2435         sti();
2436 
2437         if (set)
2438                 for (i=0; i<cmapsz ; i++)
2439                         scr_writeb(get_user(arg + i), charmap + i);
2440         else
2441                 for (i=0; i<cmapsz ; i++)
2442                         put_user(scr_readb(charmap + i), arg + i);
2443 
2444         /*
2445          * In 512-character mode, the character map is not contiguous if
2446          * we want to remain EGA compatible -- which we do
2447          */
2448 
2449         if (ch512)
2450           {
2451             charmap += 2*cmapsz;
2452             arg += cmapsz;
2453             if (set)
2454               for (i=0; i<cmapsz ; i++)
2455                 *(charmap+i) = get_user(arg+i);
2456             else
2457               for (i=0; i<cmapsz ; i++)
2458                 put_user(*(charmap+i), arg+i);
2459           };
2460 
2461         cli();
2462         outb_p( 0x00, seq_port_reg );   /* First, the sequencer */
2463         outb_p( 0x01, seq_port_val );   /* Synchronous reset */
2464         outb_p( 0x02, seq_port_reg );
2465         outb_p( 0x03, seq_port_val );   /* CPU writes to maps 0 and 1 */
2466         outb_p( 0x04, seq_port_reg );
2467         outb_p( 0x03, seq_port_val );   /* odd-even addressing */
2468         if (set)
2469           {
2470             outb_p( 0x03, seq_port_reg ); /* Character Map Select */
2471             outb_p( ch512 ? 0x04 : 0x00, seq_port_val );
2472           }
2473         outb_p( 0x00, seq_port_reg );
2474         outb_p( 0x03, seq_port_val );   /* clear synchronous reset */
2475 
2476         outb_p( 0x04, gr_port_reg );    /* Now, the graphics controller */
2477         outb_p( 0x00, gr_port_val );    /* select map 0 for CPU */
2478         outb_p( 0x05, gr_port_reg );
2479         outb_p( 0x10, gr_port_val );    /* enable even-odd addressing */
2480         outb_p( 0x06, gr_port_reg );
2481         outb_p( beg, gr_port_val );     /* map starts at b800:0 or b000:0 */
2482         if (set)                        /* attribute controller */
2483           {
2484             /* 256-char: enable intensity bit
2485                512-char: disable intensity bit */
2486             inb_p( video_port_status ); /* clear address flip-flop */
2487             outb_p ( 0x12, attrib_port ); /* color plane enable register */
2488             outb_p ( ch512 ? 0x07 : 0x0f, attrib_port );
2489             /* Wilton (1987) mentions the following; I don't know what
2490                it means, but it works, and it appears necessary */
2491             inb_p( video_port_status );
2492             outb_p ( 0x20, attrib_port );
2493           }
2494         sti();
2495 
2496         return 0;
2497 #else
2498         return -EINVAL;
2499 #endif
2500 }
2501 
2502 #define dac_reg (0x3c8)
2503 #define dac_val (0x3c9)
2504 
2505 static int set_get_cmap(unsigned char * arg, int set) {
     /* [previous][next][first][last][top][bottom][index][help] */
2506 #ifdef CAN_LOAD_PALETTE
2507         int i;
2508 
2509         /* no use to set colourmaps in less than colour VGA */
2510 
2511         if (video_type != VIDEO_TYPE_VGAC)
2512                 return -EINVAL;
2513 
2514         i = verify_area(set ? VERIFY_READ : VERIFY_WRITE, (void *)arg, 16*3);
2515         if (i)
2516                 return i;
2517 
2518         for (i=0; i<16; i++) {
2519                 if (set) {
2520                         default_red[i] = get_user(arg++) ;
2521                         default_grn[i] = get_user(arg++) ;
2522                         default_blu[i] = get_user(arg++) ;
2523                 } else {
2524                         put_user (default_red[i], arg++) ;
2525                         put_user (default_grn[i], arg++) ;
2526                         put_user (default_blu[i], arg++) ;
2527                 }
2528         }
2529         if (set) {
2530                 for (i=0; i<MAX_NR_CONSOLES; i++)
2531                         if (vc_cons_allocated(i)) {
2532                                 int j, k ;
2533                                 for (j=k=0; j<16; j++) {
2534                                         vc_cons[i].d->vc_palette[k++] = default_red[j];
2535                                         vc_cons[i].d->vc_palette[k++] = default_grn[j];
2536                                         vc_cons[i].d->vc_palette[k++] = default_blu[j];
2537                                 }
2538                         }
2539                 set_palette() ;
2540         }
2541 
2542         return 0;
2543 #else
2544         return -EINVAL;
2545 #endif
2546 }
2547 
2548 /*
2549  * Load palette into the EGA/VGA DAC registers. arg points to a colour
2550  * map, 3 bytes per colour, 16 colours, range from 0 to 255.
2551  */
2552 
2553 int con_set_cmap (unsigned char *arg)
     /* [previous][next][first][last][top][bottom][index][help] */
2554 {
2555         return set_get_cmap (arg,1);
2556 }
2557 
2558 int con_get_cmap (unsigned char *arg)
     /* [previous][next][first][last][top][bottom][index][help] */
2559 {
2560         return set_get_cmap (arg,0);
2561 }
2562 
2563 void reset_palette (int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
2564 {
2565         int j, k ;
2566         for (j=k=0; j<16; j++) {
2567                 palette[k++] = default_red[j];
2568                 palette[k++] = default_grn[j];
2569                 palette[k++] = default_blu[j];
2570         }
2571         set_palette() ;
2572 }
2573 
2574 void set_palette (void)
     /* [previous][next][first][last][top][bottom][index][help] */
2575 {
2576         int i, j ;
2577 
2578         if (video_type != VIDEO_TYPE_VGAC || console_blanked ||
2579             vt_cons[fg_console]->vc_mode == KD_GRAPHICS)
2580                 return ;
2581 
2582         for (i=j=0; i<16; i++) {
2583                 outb_p (color_table[i], dac_reg) ;
2584                 outb_p (vc_cons[fg_console].d->vc_palette[j++]>>2, dac_val) ;
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         }
2588 }
2589 
2590 /*
2591  * Load font into the EGA/VGA character generator. arg points to a 8192
2592  * byte map, 32 bytes per character. Only first H of them are used for
2593  * 8xH fonts (0 < H <= 32).
2594  */
2595 
2596 int con_set_font (char *arg, int ch512)
     /* [previous][next][first][last][top][bottom][index][help] */
2597 {
2598         int i;
2599 
2600         i = set_get_font (arg,1,ch512);
2601         if ( !i ) {
2602                 hashtable_contents_valid = 0;
2603                 video_mode_512ch = ch512;
2604                 console_charmask = ch512 ? 0x1ff : 0x0ff;
2605         }
2606         return i;
2607 }
2608 
2609 int con_get_font (char *arg)
     /* [previous][next][first][last][top][bottom][index][help] */
2610 {
2611         return set_get_font (arg,0,video_mode_512ch);
2612 }
2613 
2614 /*
2615  * Adjust the screen to fit a font of a certain height
2616  *
2617  * Returns < 0 for error, 0 if nothing changed, and the number
2618  * of lines on the adjusted console if changed.
2619  */
2620 int con_adjust_height(unsigned long fontheight)
     /* [previous][next][first][last][top][bottom][index][help] */
2621 {
2622         int rows, maxscan;
2623         unsigned char ovr, vde, fsr, curs, cure;
2624 
2625         if (fontheight > 32 || (video_type != VIDEO_TYPE_VGAC &&
2626             video_type != VIDEO_TYPE_EGAC && video_type != VIDEO_TYPE_EGAM))
2627                 return -EINVAL;
2628 
2629         if ( fontheight == video_font_height || fontheight == 0 )
2630                 return 0;
2631 
2632         video_font_height = fontheight;
2633 
2634         rows = video_scan_lines/fontheight;     /* Number of video rows we end up with */
2635         maxscan = rows*fontheight - 1;          /* Scan lines to actually display-1 */
2636 
2637         /* Reprogram the CRTC for the new font size
2638            Note: the attempt to read the overflow register will fail
2639            on an EGA, but using 0xff for the previous value appears to
2640            be OK for EGA text modes in the range 257-512 scan lines, so I
2641            guess we don't need to worry about it.
2642 
2643            The same applies for the spill bits in the font size and cursor
2644            registers; they are write-only on EGA, but it appears that they
2645            are all don't care bits on EGA, so I guess it doesn't matter. */
2646 
2647         cli();
2648         outb_p( 0x07, video_port_reg );         /* CRTC overflow register */
2649         ovr = inb_p(video_port_val);
2650         outb_p( 0x09, video_port_reg );         /* Font size register */
2651         fsr = inb_p(video_port_val);
2652         outb_p( 0x0a, video_port_reg );         /* Cursor start */
2653         curs = inb_p(video_port_val);
2654         outb_p( 0x0b, video_port_reg );         /* Cursor end */
2655         cure = inb_p(video_port_val);
2656         sti();
2657 
2658         vde = maxscan & 0xff;                   /* Vertical display end reg */
2659         ovr = (ovr & 0xbd) +                    /* Overflow register */
2660               ((maxscan & 0x100) >> 7) +
2661               ((maxscan & 0x200) >> 3);
2662         fsr = (fsr & 0xe0) + (fontheight-1);    /*  Font size register */
2663         curs = (curs & 0xc0) + fontheight - (fontheight < 10 ? 2 : 3);
2664         cure = (cure & 0xe0) + fontheight - (fontheight < 10 ? 1 : 2);
2665 
2666         cli();
2667         outb_p( 0x07, video_port_reg );         /* CRTC overflow register */
2668         outb_p( ovr, video_port_val );
2669         outb_p( 0x09, video_port_reg );         /* Font size */
2670         outb_p( fsr, video_port_val );
2671         outb_p( 0x0a, video_port_reg );         /* Cursor start */
2672         outb_p( curs, video_port_val );
2673         outb_p( 0x0b, video_port_reg );         /* Cursor end */
2674         outb_p( cure, video_port_val );
2675         outb_p( 0x12, video_port_reg );         /* Vertical display limit */
2676         outb_p( vde, video_port_val );
2677         sti();
2678 
2679         if ( rows == video_num_lines ) {
2680           /* Change didn't affect number of lines -- no need to scare
2681              the rest of the world */
2682           return 0;
2683         }
2684 
2685         vc_resize(rows, 0);                     /* Adjust console size */
2686 
2687         return rows;
2688 }

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