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

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