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

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