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

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