root/drivers/char/console.c

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

DEFINITIONS

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

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

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