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

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