root/drivers/char/console.c

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

DEFINITIONS

This source file includes following definitions.
  1. serial_echo_print
  2. serial_echo_init
  3. vc_cons_allocated
  4. vc_allocate
  5. vc_resize
  6. vc_disallocate
  7. gotoxy
  8. scrollback
  9. scrollfront
  10. set_origin
  11. scrup
  12. scrdown
  13. lf
  14. ri
  15. cr
  16. bs
  17. del
  18. csi_J
  19. csi_K
  20. csi_X
  21. update_attr
  22. default_attr
  23. csi_m
  24. respond_string
  25. cursor_report
  26. status_report
  27. respond_ID
  28. mouse_report
  29. mouse_reporting
  30. screenpos
  31. invert_screen
  32. complement_pos
  33. screen_word
  34. scrw2glyph
  35. screen_pos
  36. getconsxy
  37. putconsxy
  38. set_mode
  39. setterm_command
  40. insert_char
  41. insert_line
  42. delete_char
  43. delete_line
  44. csi_at
  45. csi_L
  46. csi_P
  47. csi_M
  48. save_cur
  49. restore_cur
  50. reset_terminal
  51. con_stop
  52. con_start
  53. con_write
  54. con_write_room
  55. con_chars_in_buffer
  56. poke_blanked_console
  57. console_print
  58. con_throttle
  59. con_unthrottle
  60. vc_init
  61. con_setsize
  62. con_init
  63. do_blank_screen
  64. do_unblank_screen
  65. blank_screen
  66. unblank_screen
  67. update_screen
  68. con_open
  69. con_set_cmap
  70. con_get_cmap
  71. reset_palette
  72. con_set_font
  73. con_get_font

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

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