root/drivers/char/console.c

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

DEFINITIONS

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

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