root/drivers/char/console.c

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

DEFINITIONS

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

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

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