root/drivers/char/console.c

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

DEFINITIONS

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

   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 blank_screen(void)'
  26  *     'void unblank_screen(void)'
  27  *     'void poke_blanked_console(void)'
  28  *     'void scrollback(int lines)'
  29  *     'void scrollfront(int lines)'
  30  *     'int do_screendump(int arg, int mode)'
  31  *
  32  *     'int con_get_font(char *)' 
  33  *     'int con_set_font(char *)' 
  34  *     'int con_get_trans(char *)'
  35  *     'int con_set_trans(char *)'
  36  *
  37  *     'int set_selection(const int arg)'
  38  *     'int paste_selection(struct tty_struct *tty)'
  39  *     'int sel_loadlut(const int arg)'
  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 /*
  73  *  NOTE!!! We sometimes disable and enable interrupts for a short while
  74  * (to put a word in video IO), but this will work even for keyboard
  75  * interrupts. We know interrupts aren't enabled when getting a keyboard
  76  * interrupt, as we use trap-gates. Hopefully all is well.
  77  */
  78 
  79 #include <linux/sched.h>
  80 #include <linux/timer.h>
  81 #include <linux/interrupt.h>
  82 #include <linux/tty.h>
  83 #include <linux/tty_flip.h>
  84 #include <linux/config.h>
  85 #include <linux/kernel.h>
  86 #include <linux/string.h>
  87 #include <linux/errno.h>
  88 #include <linux/kd.h>
  89 #include <linux/malloc.h>
  90 #include <linux/major.h>
  91 
  92 #include <asm/io.h>
  93 #include <asm/system.h>
  94 #include <asm/segment.h>
  95 #include <asm/bitops.h>
  96 
  97 #include "kbd_kern.h"
  98 #include "vt_kern.h"
  99 
 100 #ifndef MIN
 101 #define MIN(a,b)        ((a) < (b) ? (a) : (b))
 102 #endif
 103 
 104 struct tty_driver console_driver;
 105 static int console_refcount;
 106 static struct tty_struct *console_table[MAX_NR_CONSOLES];
 107 static struct termios *console_termios[MAX_NR_CONSOLES];
 108 static struct termios *console_termios_locked[MAX_NR_CONSOLES];
 109 
 110 #ifdef CONFIG_SELECTION
 111 #include <linux/ctype.h>
 112 
 113 /* Routines for selection control. */
 114 int set_selection(const int arg, struct tty_struct *tty);
 115 int paste_selection(struct tty_struct *tty);
 116 static void clear_selection(void);
 117 static void highlight_pointer(const int currcons, const int where);
 118 
 119 /* Variables for selection control. */
 120 #define SEL_BUFFER_SIZE 4096
 121 static int sel_cons = 0;
 122 static int sel_start = -1;
 123 static int sel_end;
 124 static char sel_buffer[SEL_BUFFER_SIZE] = { '\0' };
 125 #endif /* CONFIG_SELECTION */
 126 
 127 #define NPAR 16
 128 
 129 static void con_setsize(unsigned long rows, unsigned long cols);
 130 static void vc_init(unsigned int console, unsigned long rows, unsigned long cols,
 131                     int do_clear);
 132 static void get_scrmem(int currcons);
 133 static void set_scrmem(int currcons, long offset);
 134 static void set_origin(int currcons);
 135 static void gotoxy(int currcons, int new_x, int new_y);
 136 static void save_cur(int currcons);
 137 static inline void set_cursor(int currcons);
 138 static void reset_terminal(int currcons, int do_clear);
 139 extern void reset_vc(unsigned int new_console);
 140 extern void vt_init(void);
 141 extern void register_console(void (*proc)(const char *));
 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 static unsigned short   video_port_reg;         /* Video register select port   */
 151 static unsigned short   video_port_val;         /* Video register value port    */
 152 static unsigned long    video_num_columns;      /* Number of text columns       */
 153 static unsigned long    video_num_lines;        /* Number of text lines         */
 154 static unsigned long    video_size_row;
 155 static unsigned long    video_screen_size;
 156 static int can_do_color = 0;
 157 static int printable = 0;                       /* Is console ready for printing? */
 158 
 159 static unsigned short *vc_scrbuf[MAX_NR_CONSOLES];
 160 
 161 static int console_blanked = 0;
 162 static int blankinterval = 10*60*HZ;
 163 #ifndef CONFIG_VESA_PSPM
 164 static long blank_origin, blank__origin, unblank_origin;
 165 #endif
 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 #ifdef CONFIG_VESA_PSPM
 294 /*
 295  * This section(s) handles the VESA Power Saving Protocol that let a    *
 296  * monitor be powered down whenever not needed for a longer time.       *
 297  * VESA protocol defines:                                               *
 298  *                                                                      *
 299  *  Mode/Status         HSync   VSync   Video                           *
 300  *  ----------------------------------------------                      *
 301  *  "On"                on      on      active                          *
 302  *  "Suspend" {either}  on      off     blank                           *
 303  *            {  or  }  off     on      blank                           *
 304  *  "Off"               off     off     blank   <<  PSPM_FORCE_OFF      *
 305  *                                                                      *
 306  * Original code taken from the Power Management Utility (PMU) of       *
 307  * Huang shi chao, delivered together with many new monitor models      *
 308  * capable of the VESA Power Saving Protocol.                           *
 309  * Adapted to Linux by Christoph Rimek (chrimek@toppoint.de)  15-may-94 *
 310  * Re-Adapted by Nicholas Leon (nicholas@neko.binary9.com) 10/94 *
 311  *                 (with minor reorganization/changes)                          *
 312  */
 313 
 314 
 315 static void vesa_blank(void);
 316 static void vesa_unblank(void);
 317 
 318 #define seq_port_reg    (0x3c4)         /* Sequencer register select port       */
 319 #define seq_port_val    (0x3c5)         /* Sequencer register value port        */
 320 #define video_misc_rd   (0x3cc)         /* Video misc. read port        */
 321 #define video_misc_wr   (0x3c2)         /* Video misc. write port       */
 322 
 323 /* structure holding original VGA register settings */
 324 static struct {
 325         unsigned char   SeqCtrlIndex;           /* Sequencer Index reg.   */
 326         unsigned char   CrtCtrlIndex;           /* CRT-Contr. Index reg.  */
 327         unsigned char   CrtMiscIO;              /* Miscellaneous register */
 328 #ifdef CONFIG_PSPM_FORCE_OFF
 329         unsigned char   HorizontalTotal;        /* CRT-Controller:00h */
 330         unsigned char   HorizDisplayEnd;        /* CRT-Controller:01h */
 331         unsigned char   StartHorizRetrace;      /* CRT-Controller:04h */
 332         unsigned char   EndHorizRetrace;        /* CRT-Controller:05h */
 333 #endif
 334         unsigned char   Overflow;               /* CRT-Controller:07h */
 335         unsigned char   StartVertRetrace;       /* CRT-Controller:10h */
 336         unsigned char   EndVertRetrace;         /* CRT-Controller:11h */
 337         unsigned char   ModeControl;            /* CRT-Controller:17h */
 338         unsigned char   ClockingMode;           /* Seq-Controller:01h */
 339 } vga;
 340 
 341 /* routine to blank a vesa screen */
 342 static void vesa_blank(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 343 {
 344         /* save original values of VGA controller registers */
 345         cli();
 346         vga.SeqCtrlIndex = inb_p(seq_port_reg);
 347         vga.CrtCtrlIndex = inb_p(video_port_reg);
 348         vga.CrtMiscIO = inb_p(video_misc_rd);
 349         sti();
 350 #ifdef CONFIG_PSPM_FORCE_OFF
 351         outb_p(0x00,video_port_reg);                    /* HorizontalTotal */
 352         vga.HorizontalTotal = inb_p(video_port_val);
 353         outb_p(0x01,video_port_reg);                    /* HorizDisplayEnd */
 354         vga.HorizDisplayEnd = inb_p(video_port_val);
 355         outb_p(0x04,video_port_reg);                    /* StartHorizRetrace */
 356         vga.StartHorizRetrace = inb_p(video_port_val);
 357         outb_p(0x05,video_port_reg);                    /* EndHorizRetrace */
 358         vga.EndHorizRetrace = inb_p(video_port_val);
 359 #endif
 360         outb_p(0x07,video_port_reg);                    /* Overflow */
 361         vga.Overflow = inb_p(video_port_val);
 362         outb_p(0x10,video_port_reg);                    /* StartVertRetrace */
 363         vga.StartVertRetrace = inb_p(video_port_val);
 364         outb_p(0x11,video_port_reg);                    /* EndVertRetrace */
 365         vga.EndVertRetrace = inb_p(video_port_val);
 366         outb_p(0x17,video_port_reg);                    /* ModeControl */
 367         vga.ModeControl = inb_p(video_port_val);
 368         outb_p(0x01,seq_port_reg);                      /* ClockingMode */
 369         vga.ClockingMode = inb_p(seq_port_val);
 370 
 371         /* assure that video is enabled */
 372         /* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */
 373         cli();
 374         outb_p(0x01,seq_port_reg);
 375         outb_p(vga.ClockingMode | 0x20,seq_port_val);
 376 
 377 /*      sti(); 
 378         cli(); */
 379         
 380         /* test for vertical retrace in process.... */
 381         if ((vga.CrtMiscIO & 0x80) == 0x80)
 382                 outb_p(vga.CrtMiscIO & 0xef,video_misc_wr);
 383 
 384         /*  Set <End of vertical retrace> to minimum (0) and            *
 385          *  <Start of vertical Retrace> to maximum (incl. overflow)     *
 386          *  Result: turn off vertical sync (VSync) pulse                */
 387         outb_p(0x10,video_port_reg);            /* StartVertRetrace */
 388         outb_p(0xff,video_port_val);            /* maximum value */
 389         outb_p(0x11,video_port_reg);            /* EndVertRetrace */
 390         outb_p(0x40,video_port_val);            /* minimum (bits 0..3)  */
 391         outb_p(0x07,video_port_reg);            /* Overflow */
 392         outb_p(vga.Overflow | 0x84,video_port_val);     /* bits 9,10 of  */
 393                                                         /* vert. retrace */
 394 #ifdef CONFIG_PSPM_FORCE_OFF
 395         /*  Set <End of horizontal retrace> to minimum (0) and  *
 396          *  <Start of horizontal Retrace> to maximum            *
 397          *  Result: turn off horizontal sync (HSync) pulse      */
 398         outb_p(0x04,video_port_reg);            /* StartHorizRetrace */
 399         outb_p(0xff,video_port_val);            /* maximum */
 400         outb_p(0x05,video_port_reg);            /* EndHorizRetrace */
 401         outb_p(0x00,video_port_val);            /* minimum (0) */
 402 #endif
 403         /* restore both index registers */
 404         outb_p(vga.SeqCtrlIndex,seq_port_reg);
 405         outb_p(vga.CrtCtrlIndex,video_port_reg);
 406         sti();
 407 
 408 }       
 409 
 410 /* routine to unblank a vesa screen */
 411 static void vesa_unblank(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 412 {
 413         /* restore original values of VGA controller registers */
 414         cli();
 415         outb_p(vga.CrtMiscIO,video_misc_wr);
 416 #ifdef CONFIG_PSPM_FORCE_OFF
 417         outb_p(0x00,video_port_reg);            /* HorizontalTotal */
 418         outb_p(vga.HorizontalTotal,video_port_val);
 419         outb_p(0x01,video_port_reg);            /* HorizDisplayEnd */
 420         outb_p(vga.HorizDisplayEnd,video_port_val);
 421         outb_p(0x04,video_port_reg);            /* StartHorizRetrace */
 422         outb_p(vga.StartHorizRetrace,video_port_val);
 423         outb_p(0x05,video_port_reg);            /* EndHorizRetrace */
 424         outb_p(vga.EndHorizRetrace,video_port_val);
 425 #endif
 426         outb_p(0x07,video_port_reg);            /* Overflow */
 427         outb_p(vga.Overflow,video_port_val);
 428         outb_p(0x10,video_port_reg);            /* StartVertRetrace */
 429         outb_p(vga.StartVertRetrace,video_port_val);
 430         outb_p(0x11,video_port_reg);            /* EndVertRetrace */
 431         outb_p(vga.EndVertRetrace,video_port_val);
 432         outb_p(0x17,video_port_reg);            /* ModeControl */
 433         outb_p(vga.ModeControl,video_port_val);
 434         outb_p(0x01,seq_port_reg);              /* ClockingMode */
 435         outb_p(vga.ClockingMode,seq_port_val);
 436 
 437         /* restore index/control registers */
 438         outb_p(vga.SeqCtrlIndex,seq_port_reg);
 439         outb_p(vga.CrtCtrlIndex,video_port_reg);
 440         sti();
 441 }
 442 
 443 #endif /* CONFIG_VESA_PSPM */
 444 
 445 
 446 static void * memsetw(void * s, unsigned short c, unsigned int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 447 {
 448 __asm__("cld\n\t"
 449         "rep\n\t"
 450         "stosw"
 451         : /* no output */
 452         :"a" (c),"D" (s),"c" (count/2)
 453         :"cx","di");
 454 return s;
 455 }
 456 
 457 int vc_cons_allocated(unsigned int i)
     /* [previous][next][first][last][top][bottom][index][help] */
 458 {
 459         return (i < MAX_NR_CONSOLES && vc_cons[i].d);
 460 }
 461 
 462 int vc_allocate(unsigned int i)         /* return 0 on success */
     /* [previous][next][first][last][top][bottom][index][help] */
 463 {
 464         if (i >= MAX_NR_CONSOLES)
 465           return -ENODEV;
 466         if (!vc_cons[i].d) {
 467             long p, q;
 468 
 469             /* prevent users from taking too much memory */
 470             if (i >= MAX_NR_USER_CONSOLES && !suser())
 471               return -EPERM;
 472 
 473             /* due to the granularity of kmalloc, we waste some memory here */
 474             /* the alloc is done in two steps, to optimize the common situation
 475                of a 25x80 console (structsize=216, video_screen_size=4000) */
 476             q = (long) kmalloc(video_screen_size, GFP_KERNEL);
 477             if (!q)
 478               return -ENOMEM;
 479             p = (long) kmalloc(structsize, GFP_KERNEL);
 480             if (!p) {
 481                 kfree_s((char *) q, video_screen_size);
 482                 return -ENOMEM;
 483             }
 484 
 485             vc_cons[i].d = (struct vc_data *) p;
 486             p += sizeof(struct vc_data);
 487             vt_cons[i] = (struct vt_struct *) p;
 488             vc_scrbuf[i] = (unsigned short *) q;
 489             vc_cons[i].d->vc_kmalloced = 1;
 490             vc_cons[i].d->vc_screenbuf_size = video_screen_size;
 491             vc_init (i, video_num_lines, video_num_columns, 1);
 492         }
 493         return 0;
 494 }
 495 
 496 /*
 497  * Change # of rows and columns (0 means unchanged)
 498  * [this is to be used together with some user program
 499  * like resize that changes the hardware videomode]
 500  */
 501 int vc_resize(unsigned long lines, unsigned long cols)
     /* [previous][next][first][last][top][bottom][index][help] */
 502 {
 503         unsigned long cc, ll, ss, sr;
 504         unsigned long occ, oll, oss, osr;
 505         unsigned short *p;
 506         unsigned int currcons, i;
 507         unsigned short *newscreens[MAX_NR_CONSOLES];
 508         long ol, nl, rlth, rrem;
 509 
 510         cc = (cols ? cols : video_num_columns);
 511         ll = (lines ? lines : video_num_lines);
 512         sr = cc << 1;
 513         ss = sr * ll;
 514 
 515         if (ss > video_mem_term - video_mem_base)
 516           return -ENOMEM;
 517 
 518         /*
 519          * Some earlier version had all consoles of potentially
 520          * different sizes, but that was really messy.
 521          * So now we only change if there is room for all consoles
 522          * of the same size.
 523          */
 524         for (currcons = 0; currcons < MAX_NR_CONSOLES; currcons++) {
 525             if (!vc_cons_allocated(currcons))
 526               newscreens[currcons] = 0;
 527             else {
 528                 p = (unsigned short *) kmalloc(ss, GFP_USER);
 529                 if (!p) {
 530                     for (i = 0; i< currcons; i++)
 531                       if (newscreens[i])
 532                         kfree_s(newscreens[i], ss);
 533                     return -ENOMEM;
 534                 }
 535                 newscreens[currcons] = p;
 536             }
 537         }
 538 
 539         get_scrmem(fg_console);
 540 
 541         oll = video_num_lines;
 542         occ = video_num_columns;
 543         osr = video_size_row;
 544         oss = video_screen_size;
 545 
 546         video_num_lines = ll;
 547         video_num_columns = cc;
 548         video_size_row = sr;
 549         video_screen_size = ss;
 550 
 551         for (currcons = 0; currcons < MAX_NR_CONSOLES; currcons++) {
 552             if (!vc_cons_allocated(currcons))
 553               continue;
 554 
 555             rlth = MIN(osr, sr);
 556             rrem = sr - rlth;
 557             ol = origin;
 558             nl = (long) newscreens[currcons];
 559             if (ll < oll)
 560               ol += (oll - ll) * osr;
 561 
 562             while (ol < scr_end) {
 563                 memcpy((void *) nl, (void *) ol, rlth);
 564                 if (rrem)
 565                   memsetw((void *)(nl + rlth), video_erase_char, rrem);
 566                 ol += osr;
 567                 nl += sr;
 568             }
 569 
 570             if (kmalloced)
 571               kfree_s(vc_scrbuf[currcons], screenbuf_size);
 572             vc_scrbuf[currcons] = newscreens[currcons];
 573             kmalloced = 1;
 574             screenbuf_size = ss;
 575 
 576             origin = video_mem_start = (long) vc_scrbuf[currcons];
 577             scr_end = video_mem_end = video_mem_start + ss;
 578 
 579             if (scr_end > nl)
 580               memsetw((void *) nl, video_erase_char, scr_end - nl);
 581 
 582             /* do part of a reset_terminal() */
 583             top = 0;
 584             bottom = video_num_lines;
 585             gotoxy(currcons, x, y);
 586             save_cur(currcons);
 587         }
 588 
 589         set_scrmem(fg_console, 0);
 590         set_origin(fg_console);
 591         set_cursor(fg_console);
 592 
 593         return 0;
 594 }
 595 
 596 void vc_disallocate(unsigned int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 597 {
 598         if (vc_cons_allocated(currcons)) {
 599             if (kmalloced)
 600               kfree_s(vc_scrbuf[currcons], screenbuf_size);
 601             if (currcons >= MIN_NR_CONSOLES)
 602               kfree_s(vc_cons[currcons].d, structsize);
 603             vc_cons[currcons].d = 0;
 604         }
 605 }
 606 
 607 
 608 #define set_kbd(x) set_vc_kbd_mode(kbd_table+currcons,x)
 609 #define clr_kbd(x) clr_vc_kbd_mode(kbd_table+currcons,x)
 610 #define is_kbd(x) vc_kbd_mode(kbd_table+currcons,x)
 611 
 612 #define decarm          VC_REPEAT
 613 #define decckm          VC_CKMODE
 614 #define kbdapplic       VC_APPLIC
 615 #define lnm             VC_CRLF
 616 
 617 /*
 618  * this is what the terminal answers to a ESC-Z or csi0c query.
 619  */
 620 #define VT100ID "\033[?1;2c"
 621 #define VT102ID "\033[?6c"
 622 
 623 static unsigned char * translations[] = {
 624 /* 8-bit Latin-1 mapped to the PC character set: '\0' means non-printable */
 625 (unsigned char *)
 626         "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
 627         "\0\0\0\0\0\0\0\0\0\0\376\0\0\0\0\0"
 628         " !\"#$%&'()*+,-./0123456789:;<=>?"
 629         "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
 630         "`abcdefghijklmnopqrstuvwxyz{|}~\0"
 631         "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
 632         "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
 633         "\377\255\233\234\376\235\174\025\376\376\246\256\252\055\376\376"
 634         "\370\361\375\376\376\346\024\371\376\376\247\257\254\253\376\250"
 635         "\376\376\376\376\216\217\222\200\376\220\376\376\376\376\376\376"
 636         "\376\245\376\376\376\376\231\376\350\376\376\376\232\376\376\341"
 637         "\205\240\203\376\204\206\221\207\212\202\210\211\215\241\214\213"
 638         "\376\244\225\242\223\376\224\366\355\227\243\226\201\376\376\230",
 639 /* vt100 graphics */
 640 (unsigned char *)
 641         "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
 642         "\0\0\0\0\0\0\0\0\0\0\376\0\0\0\0\0"
 643         " !\"#$%&'()*+,-./0123456789:;<=>?"
 644         "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^ "
 645         "\004\261\007\007\007\007\370\361\007\007\331\277\332\300\305\304"
 646         "\304\304\137\137\303\264\301\302\263\363\362\343\330\234\007\0"
 647         "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
 648         "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
 649         "\377\255\233\234\376\235\174\025\376\376\246\256\252\055\376\376"
 650         "\370\361\375\376\376\346\024\371\376\376\247\257\254\253\376\250"
 651         "\376\376\376\376\216\217\222\200\376\220\376\376\376\376\376\376"
 652         "\376\245\376\376\376\376\231\376\376\376\376\376\232\376\376\341"
 653         "\205\240\203\376\204\206\221\207\212\202\210\211\215\241\214\213"
 654         "\376\244\225\242\223\376\224\366\376\227\243\226\201\376\376\230",
 655 /* IBM graphics: minimal translations (BS, CR, LF, LL, SO, SI and ESC) */
 656 (unsigned char *)
 657         "\000\001\002\003\004\005\006\007\000\011\000\013\000\000\000\000"
 658         "\020\021\022\023\024\025\026\027\030\031\032\000\034\035\036\037"
 659         "\040\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057"
 660         "\060\061\062\063\064\065\066\067\070\071\072\073\074\075\076\077"
 661         "\100\101\102\103\104\105\106\107\110\111\112\113\114\115\116\117"
 662         "\120\121\122\123\124\125\126\127\130\131\132\133\134\135\136\137"
 663         "\140\141\142\143\144\145\146\147\150\151\152\153\154\155\156\157"
 664         "\160\161\162\163\164\165\166\167\170\171\172\173\174\175\176\177"
 665         "\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217"
 666         "\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237"
 667         "\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257"
 668         "\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277"
 669         "\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317"
 670         "\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337"
 671         "\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357"
 672         "\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377",
 673  /* USER: customizable mappings, initialized as the previous one (IBM) */
 674 (unsigned char *)
 675         "\000\001\002\003\004\005\006\007\010\011\000\013\000\000\016\017"
 676         "\020\021\022\023\024\025\026\027\030\031\032\000\034\035\036\037"
 677         "\040\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057"
 678         "\060\061\062\063\064\065\066\067\070\071\072\073\074\075\076\077"
 679         "\100\101\102\103\104\105\106\107\110\111\112\113\114\115\116\117"
 680         "\120\121\122\123\124\125\126\127\130\131\132\133\134\135\136\137"
 681         "\140\141\142\143\144\145\146\147\150\151\152\153\154\155\156\157"
 682         "\160\161\162\163\164\165\166\167\170\171\172\173\174\175\176\177"
 683         "\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217"
 684         "\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237"
 685         "\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257"
 686         "\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277"
 687         "\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317"
 688         "\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337"
 689         "\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357"
 690         "\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377"
 691 };
 692 
 693 #define NORM_TRANS (translations[0])
 694 #define GRAF_TRANS (translations[1])
 695 #define NULL_TRANS (translations[2])
 696 #define USER_TRANS (translations[3])
 697 
 698 static unsigned char color_table[] = { 0, 4, 2, 6, 1, 5, 3, 7,
 699                                        8,12,10,14, 9,13,11,15 };
 700 
 701 /*
 702  * gotoxy() must verify all boundaries, because the arguments
 703  * might also be negative. If the given position is out of
 704  * bounds, the cursor is placed at the nearest margin.
 705  */
 706 static void gotoxy(int currcons, int new_x, int new_y)
     /* [previous][next][first][last][top][bottom][index][help] */
 707 {
 708         int max_y;
 709 
 710         if (new_x < 0)
 711                 x = 0;
 712         else
 713                 if (new_x >= video_num_columns)
 714                         x = video_num_columns - 1;
 715                 else
 716                         x = new_x;
 717         if (decom) {
 718                 new_y += top;
 719                 max_y = bottom;
 720         } else
 721                 max_y = video_num_lines;
 722         if (new_y < 0)
 723                 y = 0;
 724         else
 725                 if (new_y >= max_y)
 726                         y = max_y - 1;
 727                 else
 728                         y = new_y;
 729         pos = origin + y*video_size_row + (x<<1);
 730         need_wrap = 0;
 731 }
 732 
 733 /*
 734  * *Very* limited hardware scrollback support..
 735  */
 736 static unsigned short __real_origin;
 737 static unsigned short __origin;         /* offset of currently displayed screen */
 738 
 739 static inline void __set_origin(unsigned short offset)
     /* [previous][next][first][last][top][bottom][index][help] */
 740 {
 741         unsigned long flags;
 742 #ifdef CONFIG_SELECTION
 743         clear_selection();
 744 #endif /* CONFIG_SELECTION */
 745         save_flags(flags); cli();
 746         __origin = offset;
 747         outb_p(12, video_port_reg);
 748         outb_p(offset >> 8, video_port_val);
 749         outb_p(13, video_port_reg);
 750         outb_p(offset, video_port_val);
 751         restore_flags(flags);
 752 }
 753 
 754 void scrollback(int lines)
     /* [previous][next][first][last][top][bottom][index][help] */
 755 {
 756         if (!lines)
 757                 lines = video_num_lines/2;
 758         lines *= video_num_columns;
 759         lines = __origin - lines;
 760         if (lines < 0)
 761                 lines = 0;
 762         __set_origin(lines);
 763 }
 764 
 765 void scrollfront(int lines)
     /* [previous][next][first][last][top][bottom][index][help] */
 766 {
 767         if (!lines)
 768                 lines = video_num_lines/2;
 769         lines *= video_num_columns;
 770         lines = __origin + lines;
 771         if (lines > __real_origin)
 772                 lines = __real_origin;
 773         __set_origin(lines);
 774 }
 775 
 776 static void set_origin(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 777 {
 778         if (video_type != VIDEO_TYPE_EGAC && video_type != VIDEO_TYPE_EGAM)
 779                 return;
 780         if (currcons != fg_console || console_blanked || vcmode == KD_GRAPHICS)
 781                 return;
 782         __real_origin = (origin-video_mem_base) >> 1;
 783         __set_origin(__real_origin);
 784 }
 785 
 786 /*
 787  * Put the cursor just beyond the end of the display adaptor memory.
 788  */
 789 static inline void hide_cursor(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 790 {
 791   /* This is inefficient, we could just put the cursor at 0xffff,
 792      but perhaps the delays due to the inefficiency are useful for
 793      some hardware... */
 794         outb_p(14, video_port_reg);
 795         outb_p(0xff&((video_mem_term-video_mem_base)>>9), video_port_val);
 796         outb_p(15, video_port_reg);
 797         outb_p(0xff&((video_mem_term-video_mem_base)>>1), video_port_val);
 798 }
 799 
 800 static inline void set_cursor(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 801 {
 802         unsigned long flags;
 803 
 804         if (currcons != fg_console || console_blanked || vcmode == KD_GRAPHICS)
 805                 return;
 806         if (__real_origin != __origin)
 807                 __set_origin(__real_origin);
 808         save_flags(flags); cli();
 809         if (deccm) {
 810                 outb_p(14, video_port_reg);
 811                 outb_p(0xff&((pos-video_mem_base)>>9), video_port_val);
 812                 outb_p(15, video_port_reg);
 813                 outb_p(0xff&((pos-video_mem_base)>>1), video_port_val);
 814         } else
 815                 hide_cursor();
 816         restore_flags(flags);
 817 }
 818 
 819 static void scrup(int currcons, unsigned int t, unsigned int b)
     /* [previous][next][first][last][top][bottom][index][help] */
 820 {
 821         int hardscroll = 1;
 822 
 823         if (b > video_num_lines || t >= b)
 824                 return;
 825         if (video_type != VIDEO_TYPE_EGAC && video_type != VIDEO_TYPE_EGAM)
 826                 hardscroll = 0;
 827         else if (t || b != video_num_lines)
 828                 hardscroll = 0;
 829         if (hardscroll) {
 830                 origin += video_size_row;
 831                 pos += video_size_row;
 832                 scr_end += video_size_row;
 833                 if (scr_end > video_mem_end) {
 834                         __asm__("cld\n\t"
 835                                 "rep\n\t"
 836                                 "movsl\n\t"
 837                                 "movl _video_num_columns,%1\n\t"
 838                                 "rep\n\t"
 839                                 "stosw"
 840                                 : /* no output */
 841                                 :"a" (video_erase_char),
 842                                 "c" ((video_num_lines-1)*video_num_columns>>1),
 843                                 "D" (video_mem_start),
 844                                 "S" (origin)
 845                                 :"cx","di","si");
 846                         scr_end -= origin-video_mem_start;
 847                         pos -= origin-video_mem_start;
 848                         origin = video_mem_start;
 849                         has_scrolled = 1;
 850                 } else {
 851                         __asm__("cld\n\t"
 852                                 "rep\n\t"
 853                                 "stosw"
 854                                 : /* no output */
 855                                 :"a" (video_erase_char),
 856                                 "c" (video_num_columns),
 857                                 "D" (scr_end-video_size_row)
 858                                 :"cx","di");
 859                 }
 860                 set_origin(currcons);
 861         } else {
 862                 __asm__("cld\n\t"
 863                         "rep\n\t"
 864                         "movsl\n\t"
 865                         "movl _video_num_columns,%%ecx\n\t"
 866                         "rep\n\t"
 867                         "stosw"
 868                         : /* no output */
 869                         :"a" (video_erase_char),
 870                         "c" ((b-t-1)*video_num_columns>>1),
 871                         "D" (origin+video_size_row*t),
 872                         "S" (origin+video_size_row*(t+1))
 873                         :"cx","di","si");
 874         }
 875 }
 876 
 877 static void scrdown(int currcons, unsigned int t, unsigned int b)
     /* [previous][next][first][last][top][bottom][index][help] */
 878 {
 879         if (b > video_num_lines || t >= b)
 880                 return;
 881         __asm__("std\n\t"
 882                 "rep\n\t"
 883                 "movsl\n\t"
 884                 "addl $2,%%edi\n\t"     /* %edi has been decremented by 4 */
 885                 "movl _video_num_columns,%%ecx\n\t"
 886                 "rep\n\t"
 887                 "stosw\n\t"
 888                 "cld"
 889                 : /* no output */
 890                 :"a" (video_erase_char),
 891                 "c" ((b-t-1)*video_num_columns>>1),
 892                 "D" (origin+video_size_row*b-4),
 893                 "S" (origin+video_size_row*(b-1)-4)
 894                 :"ax","cx","di","si");
 895         has_scrolled = 1;
 896 }
 897 
 898 static void lf(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 899 {
 900         /* don't scroll if above bottom of scrolling region, or
 901          * if below scrolling region
 902          */
 903         if (y+1 == bottom)
 904                 scrup(currcons,top,bottom);
 905         else if (y < video_num_lines-1) {
 906                 y++;
 907                 pos += video_size_row;
 908         }
 909         need_wrap = 0;
 910 }
 911 
 912 static void ri(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 913 {
 914         /* don't scroll if below top of scrolling region, or
 915          * if above scrolling region
 916          */
 917         if (y == top)
 918                 scrdown(currcons,top,bottom);
 919         else if (y > 0) {
 920                 y--;
 921                 pos -= video_size_row;
 922         }
 923         need_wrap = 0;
 924 }
 925 
 926 static inline void cr(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 927 {
 928         pos -= x<<1;
 929         need_wrap = x = 0;
 930 }
 931 
 932 static inline void bs(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 933 {
 934         if (x) {
 935                 pos -= 2;
 936                 x--;
 937                 need_wrap = 0;
 938         }
 939 }
 940 
 941 static inline void del(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 942 {
 943         /* ignored */
 944 }
 945 
 946 static void csi_J(int currcons, int vpar)
     /* [previous][next][first][last][top][bottom][index][help] */
 947 {
 948         unsigned long count;
 949         unsigned long start;
 950 
 951         switch (vpar) {
 952                 case 0: /* erase from cursor to end of display */
 953                         count = (scr_end-pos)>>1;
 954                         start = pos;
 955                         break;
 956                 case 1: /* erase from start to cursor */
 957                         count = ((pos-origin)>>1)+1;
 958                         start = origin;
 959                         break;
 960                 case 2: /* erase whole display */
 961                         count = video_num_columns * video_num_lines;
 962                         start = origin;
 963                         break;
 964                 default:
 965                         return;
 966         }
 967         __asm__("cld\n\t"
 968                 "rep\n\t"
 969                 "stosw\n\t"
 970                 : /* no output */
 971                 :"c" (count),
 972                 "D" (start),"a" (video_erase_char)
 973                 :"cx","di");
 974         need_wrap = 0;
 975 }
 976 
 977 static void csi_K(int currcons, int vpar)
     /* [previous][next][first][last][top][bottom][index][help] */
 978 {
 979         long count;
 980         long start;
 981 
 982         switch (vpar) {
 983                 case 0: /* erase from cursor to end of line */
 984                         count = video_num_columns-x;
 985                         start = pos;
 986                         break;
 987                 case 1: /* erase from start of line to cursor */
 988                         start = pos - (x<<1);
 989                         count = x+1;
 990                         break;
 991                 case 2: /* erase whole line */
 992                         start = pos - (x<<1);
 993                         count = video_num_columns;
 994                         break;
 995                 default:
 996                         return;
 997         }
 998         __asm__("cld\n\t"
 999                 "rep\n\t"
1000                 "stosw\n\t"
1001                 : /* no output */
1002                 :"c" (count),
1003                 "D" (start),"a" (video_erase_char)
1004                 :"cx","di");
1005         need_wrap = 0;
1006 }
1007 
1008 static void csi_X(int currcons, int vpar) /* erase the following vpar positions */
     /* [previous][next][first][last][top][bottom][index][help] */
1009 {                                         /* not vt100? */
1010         long count;
1011         long start;
1012 
1013         if (!vpar)
1014                 vpar++;
1015 
1016         start=pos;
1017         count=(vpar > video_num_columns-x) ? (video_num_columns-x) : vpar;
1018 
1019         __asm__("cld\n\t"
1020                 "rep\n\t"
1021                 "stosw\n\t"
1022                 : /* no output */
1023                 :"c" (count),
1024                 "D" (start),"a" (video_erase_char)
1025                 :"cx","di");
1026         need_wrap = 0;
1027 }
1028 
1029 static void update_attr(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
1030 {
1031         attr = color;
1032         if (can_do_color) {
1033                 if (underline)
1034                         attr = (attr & 0xf0) | ulcolor;
1035                 else if (intensity == 0)
1036                         attr = (attr & 0xf0) | halfcolor;
1037         }
1038         if (reverse ^ decscnm)
1039                 attr = (attr & 0x88) | (((attr >> 4) | (attr << 4)) & 0x77);
1040         if (blink)
1041                 attr ^= 0x80;
1042         if (intensity == 2)
1043                 attr ^= 0x08;
1044         if (!can_do_color) {
1045                 if (underline)
1046                         attr = (attr & 0xf8) | 0x01;
1047                 else if (intensity == 0)
1048                         attr = (attr & 0xf0) | 0x08;
1049         }
1050         if (decscnm)
1051                 video_erase_char = (((color & 0x88) | (((color >> 4) | (color << 4)) & 0x77)) << 8) | ' ';
1052         else
1053                 video_erase_char = (color << 8) | ' ';
1054 }
1055 
1056 static void default_attr(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
1057 {
1058         intensity = 1;
1059         underline = 0;
1060         reverse = 0;
1061         blink = 0;
1062         color = def_color;
1063 }
1064 
1065 static void csi_m(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
1066 {
1067         int i;
1068 
1069         for (i=0;i<=npar;i++)
1070                 switch (par[i]) {
1071                         case 0: /* all attributes off */
1072                                 default_attr(currcons);
1073                                 break;
1074                         case 1:
1075                                 intensity = 2;
1076                                 break;
1077                         case 2:
1078                                 intensity = 0;
1079                                 break;
1080                         case 4:
1081                                 underline = 1;
1082                                 break;
1083                         case 5:
1084                                 blink = 1;
1085                                 break;
1086                         case 7:
1087                                 reverse = 1;
1088                                 break;
1089                         case 10: /* ANSI X3.64-1979 (SCO-ish?)
1090                                   * Select primary font, don't display
1091                                   * control chars if defined, don't set
1092                                   * bit 8 on output.
1093                                   */
1094                                 translate = (charset == 0
1095                                                 ? G0_charset
1096                                                 : G1_charset);
1097                                 disp_ctrl = 0;
1098                                 toggle_meta = 0;
1099                                 break;
1100                         case 11: /* ANSI X3.64-1979 (SCO-ish?)
1101                                   * Select first alternate font, let's
1102                                   * chars < 32 be displayed as ROM chars.
1103                                   */
1104                                 translate = NULL_TRANS;
1105                                 disp_ctrl = 1;
1106                                 toggle_meta = 0;
1107                                 break;
1108                         case 12: /* ANSI X3.64-1979 (SCO-ish?)
1109                                   * Select second alternate font, toggle
1110                                   * high bit before displaying as ROM char.
1111                                   */
1112                                 translate = NULL_TRANS;
1113                                 disp_ctrl = 1;
1114                                 toggle_meta = 1;
1115                                 break;
1116                         case 21:
1117                         case 22:
1118                                 intensity = 1;
1119                                 break;
1120                         case 24:
1121                                 underline = 0;
1122                                 break;
1123                         case 25:
1124                                 blink = 0;
1125                                 break;
1126                         case 27:
1127                                 reverse = 0;
1128                                 break;
1129                         case 38: /* ANSI X3.64-1979 (SCO-ish?)
1130                                   * Enables underscore, white foreground
1131                                   * with white underscore (Linux - use
1132                                   * default foreground).
1133                                   */
1134                                 color = (def_color & 0x0f) | background;
1135                                 underline = 1;
1136                                 break;
1137                         case 39: /* ANSI X3.64-1979 (SCO-ish?)
1138                                   * Disable underline option.
1139                                   * Reset colour to default? It did this
1140                                   * before...
1141                                   */
1142                                 color = (def_color & 0x0f) | background;
1143                                 underline = 0;
1144                                 break;
1145                         case 49:
1146                                 color = (def_color & 0xf0) | foreground;
1147                                 break;
1148                         default:
1149                                 if (par[i] >= 30 && par[i] <= 37)
1150                                         color = color_table[par[i]-30]
1151                                                 | background; 
1152                                 else if (par[i] >= 40 && par[i] <= 47)
1153                                         color = (color_table[par[i]-40]<<4)
1154                                                 | foreground;
1155                                 break;
1156                 }
1157         update_attr(currcons);
1158 }
1159 
1160 static void respond_string(char * p, struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
1161 {
1162         while (*p) {
1163                 tty_insert_flip_char(tty, *p, 0);
1164                 p++;
1165         }
1166         tty_schedule_flip(tty);
1167 }
1168 
1169 static void cursor_report(int currcons, struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
1170 {
1171         char buf[40];
1172 
1173         sprintf(buf, "\033[%ld;%ldR", y + (decom ? top+1 : 1), x+1);
1174         respond_string(buf, tty);
1175 }
1176 
1177 #ifdef CONFIG_SELECTION
1178 static void mouse_report(int currcons, struct tty_struct * tty,
     /* [previous][next][first][last][top][bottom][index][help] */
1179                          int butt, int mrx, int mry)
1180 {
1181         char buf[8];
1182 
1183         sprintf(buf, "\033[M%c%c%c", (char)(' ' + butt), (char)('!' + mrx),
1184                 (char)('!' + mry));
1185         respond_string(buf, tty);
1186 }
1187 #endif
1188 
1189 static inline void status_report(int currcons, struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
1190 {
1191         respond_string("\033[0n", tty); /* Terminal ok */
1192 }
1193 
1194 static inline void respond_ID(int currcons, struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
1195 {
1196         respond_string(VT102ID, tty);
1197 }
1198 
1199 static void invert_screen(int currcons) {
     /* [previous][next][first][last][top][bottom][index][help] */
1200         unsigned char *p;
1201 
1202         if (can_do_color)
1203                 for (p = (unsigned char *)origin+1; p < (unsigned char *)scr_end; p+=2)
1204                         *p = (*p & 0x88) | (((*p >> 4) | (*p << 4)) & 0x77);
1205         else
1206                 for (p = (unsigned char *)origin+1; p < (unsigned char *)scr_end; p+=2)
1207                         *p ^= *p & 0x07 == 1 ? 0x70 : 0x77;
1208 }
1209 
1210 static void set_mode(int currcons, int on_off)
     /* [previous][next][first][last][top][bottom][index][help] */
1211 {
1212         int i;
1213 
1214         for (i=0; i<=npar; i++)
1215                 if (ques) switch(par[i]) {      /* DEC private modes set/reset */
1216                         case 1:                 /* Cursor keys send ^[Ox/^[[x */
1217                                 if (on_off)
1218                                         set_kbd(decckm);
1219                                 else
1220                                         clr_kbd(decckm);
1221                                 break;
1222                         case 3: /* 80/132 mode switch unimplemented */
1223                                 deccolm = on_off;
1224 #if 0
1225                                 (void) vc_resize(video_num_lines, deccolm ? 132 : 80);
1226                                 /* this alone does not suffice; some user mode
1227                                    utility has to change the hardware regs */
1228 #endif
1229                                 break;
1230                         case 5:                 /* Inverted screen on/off */
1231                                 if (decscnm != on_off) {
1232                                         decscnm = on_off;
1233                                         invert_screen(currcons);
1234                                         update_attr(currcons);
1235                                 }
1236                                 break;
1237                         case 6:                 /* Origin relative/absolute */
1238                                 decom = on_off;
1239                                 gotoxy(currcons,0,0);
1240                                 break;
1241                         case 7:                 /* Autowrap on/off */
1242                                 decawm = on_off;
1243                                 break;
1244                         case 8:                 /* Autorepeat on/off */
1245                                 if (on_off)
1246                                         set_kbd(decarm);
1247                                 else
1248                                         clr_kbd(decarm);
1249                                 break;
1250                         case 9:
1251                                 report_mouse = on_off ? 1 : 0;
1252                                 break;
1253                         case 25:                /* Cursor on/off */
1254                                 deccm = on_off;
1255                                 set_cursor(currcons);
1256                                 break;
1257                         case 1000:
1258                                 report_mouse = on_off ? 2 : 0;
1259                                 break;
1260                 } else switch(par[i]) {         /* ANSI modes set/reset */
1261                         case 4:                 /* Insert Mode on/off */
1262                                 decim = on_off;
1263                                 break;
1264                         case 20:                /* Lf, Enter == CrLf/Lf */
1265                                 if (on_off)
1266                                         set_kbd(lnm);
1267                                 else
1268                                         clr_kbd(lnm);
1269                                 break;
1270                 }
1271 }
1272 
1273 static void setterm_command(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
1274 {
1275         switch(par[0]) {
1276                 case 1: /* set color for underline mode */
1277                         if (can_do_color && par[1] < 16) {
1278                                 ulcolor = color_table[par[1]];
1279                                 if (underline)
1280                                         update_attr(currcons);
1281                         }
1282                         break;
1283                 case 2: /* set color for half intensity mode */
1284                         if (can_do_color && par[1] < 16) {
1285                                 halfcolor = color_table[par[1]];
1286                                 if (intensity == 0)
1287                                         update_attr(currcons);
1288                         }
1289                         break;
1290                 case 8: /* store colors as defaults */
1291                         def_color = attr;
1292                         default_attr(currcons);
1293                         update_attr(currcons);
1294                         break;
1295                 case 9: /* set blanking interval */
1296                         blankinterval = ((par[1] < 60) ? par[1] : 60) * 60 * HZ;
1297                         break;
1298         }
1299 }
1300 
1301 static void insert_char(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
1302 {
1303         unsigned int i = x;
1304         unsigned short tmp, old = video_erase_char;
1305         unsigned short * p = (unsigned short *) pos;
1306 
1307         while (i++ < video_num_columns) {
1308                 tmp = *p;
1309                 *p = old;
1310                 old = tmp;
1311                 p++;
1312         }
1313         need_wrap = 0;
1314 }
1315 
1316 static void insert_line(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
1317 {
1318         scrdown(currcons,y,bottom);
1319         need_wrap = 0;
1320 }
1321 
1322 static void delete_char(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
1323 {
1324         unsigned int i = x;
1325         unsigned short * p = (unsigned short *) pos;
1326 
1327         while (++i < video_num_columns) {
1328                 *p = *(p+1);
1329                 p++;
1330         }
1331         *p = video_erase_char;
1332         need_wrap = 0;
1333 }
1334 
1335 static void delete_line(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
1336 {
1337         scrup(currcons,y,bottom);
1338         need_wrap = 0;
1339 }
1340 
1341 static void csi_at(int currcons, unsigned int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
1342 {
1343         if (nr > video_num_columns)
1344                 nr = video_num_columns;
1345         else if (!nr)
1346                 nr = 1;
1347         while (nr--)
1348                 insert_char(currcons);
1349 }
1350 
1351 static void csi_L(int currcons, unsigned int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
1352 {
1353         if (nr > video_num_lines)
1354                 nr = video_num_lines;
1355         else if (!nr)
1356                 nr = 1;
1357         while (nr--)
1358                 insert_line(currcons);
1359 }
1360 
1361 static void csi_P(int currcons, unsigned int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
1362 {
1363         if (nr > video_num_columns)
1364                 nr = video_num_columns;
1365         else if (!nr)
1366                 nr = 1;
1367         while (nr--)
1368                 delete_char(currcons);
1369 }
1370 
1371 static void csi_M(int currcons, unsigned int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
1372 {
1373         if (nr > video_num_lines)
1374                 nr = video_num_lines;
1375         else if (!nr)
1376                 nr=1;
1377         while (nr--)
1378                 delete_line(currcons);
1379 }
1380 
1381 static void save_cur(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
1382 {
1383         saved_x         = x;
1384         saved_y         = y;
1385         s_intensity     = intensity;
1386         s_underline     = underline;
1387         s_blink         = blink;
1388         s_reverse       = reverse;
1389         s_charset       = charset;
1390         s_color         = color;
1391         saved_G0        = G0_charset;
1392         saved_G1        = G1_charset;
1393 }
1394 
1395 static void restore_cur(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
1396 {
1397         gotoxy(currcons,saved_x,saved_y);
1398         intensity       = s_intensity;
1399         underline       = s_underline;
1400         blink           = s_blink;
1401         reverse         = s_reverse;
1402         charset         = s_charset;
1403         color           = s_color;
1404         G0_charset      = saved_G0;
1405         G1_charset      = saved_G1;
1406         translate       = charset ? G1_charset : G0_charset;
1407         update_attr(currcons);
1408         need_wrap = 0;
1409 }
1410 
1411 enum { ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey, 
1412         EShash, ESsetG0, ESsetG1, ESpercent, ESignore };
1413 
1414 static void reset_terminal(int currcons, int do_clear)
     /* [previous][next][first][last][top][bottom][index][help] */
1415 {
1416         top             = 0;
1417         bottom          = video_num_lines;
1418         vc_state        = ESnormal;
1419         ques            = 0;
1420         translate       = NORM_TRANS;
1421         G0_charset      = NORM_TRANS;
1422         G1_charset      = GRAF_TRANS;
1423         charset         = 0;
1424         need_wrap       = 0;
1425         report_mouse    = 0;
1426         utf             = 0;
1427         utf_count       = 0;
1428 
1429         disp_ctrl       = 0;
1430         toggle_meta     = 0;
1431 
1432         decscnm         = 0;
1433         decom           = 0;
1434         decawm          = 1;
1435         deccm           = 1;
1436         decim           = 0;
1437 
1438         set_kbd(decarm);
1439         clr_kbd(decckm);
1440         clr_kbd(kbdapplic);
1441         clr_kbd(lnm);
1442         kbd_table[currcons].lockstate = 0;
1443         kbd_table[currcons].ledmode = LED_SHOW_FLAGS;
1444         kbd_table[currcons].ledflagstate = kbd_table[currcons].default_ledflagstate;
1445         set_leds();
1446 
1447         default_attr(currcons);
1448         update_attr(currcons);
1449 
1450         tab_stop[0]     = 0x01010100;
1451         tab_stop[1]     =
1452         tab_stop[2]     =
1453         tab_stop[3]     =
1454         tab_stop[4]     = 0x01010101;
1455 
1456         gotoxy(currcons,0,0);
1457         save_cur(currcons);
1458         if (do_clear)
1459             csi_J(currcons,2);
1460 }
1461 
1462 /*
1463  * Turn the Scroll-Lock LED on when the tty is stopped
1464  */
1465 static void con_stop(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
1466 {
1467         int console_num;
1468         if (!tty)
1469                 return;
1470         console_num = MINOR(tty->device) - (tty->driver.minor_start);
1471         if (!vc_cons_allocated(console_num))
1472                 return;
1473         set_vc_kbd_led(kbd_table + console_num, VC_SCROLLOCK);
1474         set_leds();
1475 }
1476 
1477 /*
1478  * Turn the Scroll-Lock LED off when the console is started
1479  */
1480 static void con_start(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
1481 {
1482         int console_num;
1483         if (!tty)
1484                 return;
1485         console_num = MINOR(tty->device) - (tty->driver.minor_start);
1486         if (!vc_cons_allocated(console_num))
1487                 return;
1488         clr_vc_kbd_led(kbd_table + console_num, VC_SCROLLOCK);
1489         set_leds();
1490 }
1491 
1492 static int con_write(struct tty_struct * tty, int from_user,
     /* [previous][next][first][last][top][bottom][index][help] */
1493                      unsigned char *buf, int count)
1494 {
1495         int c, tc, ok, n = 0;
1496         unsigned int currcons;
1497         struct vt_struct *vt = (struct vt_struct *)tty->driver_data;
1498 
1499         currcons = vt->vc_num;
1500         if (!vc_cons_allocated(currcons)) {
1501             /* could this happen? */
1502             static int error = 0;
1503             if (!error) {
1504                 error = 1;
1505                 printk("con_write: tty %d not allocated\n", currcons+1);
1506             }
1507             return 0;
1508         }
1509 #ifdef CONFIG_SELECTION
1510         /* clear the selection */
1511         if (currcons == sel_cons)
1512                 clear_selection();
1513 #endif /* CONFIG_SELECTION */
1514         disable_bh(KEYBOARD_BH);
1515         while (!tty->stopped && count) {
1516                 c = from_user ? get_fs_byte(buf) : *buf;
1517                 buf++; n++; count--;
1518 
1519                 if (utf) {
1520                     /* Combine UTF-8 into Unicode */
1521                     /* Incomplete characters silently ignored */
1522                     if(c > 0x7f) {   
1523                         /* UTF-8 to Latin-1 decoding */
1524                         if (utf_count > 0 && (c & 0xc0) == 0x80) {
1525                                 utf_char = (utf_char << 6) | (c & 0x3f);
1526                                 utf_count--;
1527                                 if (utf_count == 0)
1528                                     c = utf_char;
1529                                 else continue;
1530                         } else {
1531                                 if ((c & 0xe0) == 0xc0) {
1532                                     utf_count = 1;
1533                                     utf_char = (c & 0x1f);
1534                                 } else if ((c & 0xf0) == 0xe0) {
1535                                     utf_count = 2;
1536                                     utf_char = (c & 0x0f);
1537                                 } else
1538                                     utf_count = 0;
1539                                 continue;
1540                         }
1541                     } else
1542                         utf_count = 0;
1543 
1544                     /* Now try to find out how to display it */
1545                     if (c > 0xff) {
1546                         tc = conv_uni_to_pc(c);
1547                         if (tc == -2)
1548                           continue;
1549                         vc_state = ESnormal;
1550                         if (tc == -1)
1551                           tc = 0376;    /* small square: symbol not found */
1552                         ok = 1;
1553                     } else {
1554                         tc = NORM_TRANS[c];
1555                         ok = 0;
1556                     }
1557                 } else {        /* no utf */
1558                     tc = translate[toggle_meta ? (c|0x80) : c];
1559                     ok = 0;
1560                 }
1561 
1562                 /* Can print ibm (even if 0), and latin1 provided
1563                    it is a printing char or control chars are printed ^@ */
1564                 if (!ok && tc && (c >= 32 || (disp_ctrl && (c&0x7f) != 27)))
1565                     ok = 1;
1566 
1567                 if (vc_state == ESnormal && ok) {
1568                         if (need_wrap) {
1569                                 cr(currcons);
1570                                 lf(currcons);
1571                         }
1572                         if (decim)
1573                                 insert_char(currcons);
1574                         *(unsigned short *) pos = (attr << 8) + tc;
1575                         if (x == video_num_columns - 1)
1576                                 need_wrap = decawm;
1577                         else {
1578                                 x++;
1579                                 pos+=2;
1580                         }
1581                         continue;
1582                 }
1583 
1584                 /*
1585                  *  Control characters can be used in the _middle_
1586                  *  of an escape sequence.
1587                  */
1588                 switch (c) {
1589                         case 7:
1590                                 kd_mksound(0x637, HZ/8);
1591                                 continue;
1592                         case 8:
1593                                 bs(currcons);
1594                                 continue;
1595                         case 9:
1596                                 pos -= (x << 1);
1597                                 while (x < video_num_columns - 1) {
1598                                         x++;
1599                                         if (tab_stop[x >> 5] & (1 << (x & 31)))
1600                                                 break;
1601                                 }
1602                                 pos += (x << 1);
1603                                 continue;
1604                         case 10: case 11: case 12:
1605                                 lf(currcons);
1606                                 if (!is_kbd(lnm))
1607                                         continue;
1608                         case 13:
1609                                 cr(currcons);
1610                                 continue;
1611                         case 14:
1612                                 charset = 1;
1613                                 translate = G1_charset;
1614                                 continue;
1615                         case 15:
1616                                 charset = 0;
1617                                 translate = G0_charset;
1618                                 continue;
1619                         case 24: case 26:
1620                                 vc_state = ESnormal;
1621                                 continue;
1622                         case 27:
1623                                 vc_state = ESesc;
1624                                 continue;
1625                         case 127:
1626                                 del(currcons);
1627                                 continue;
1628                         case 128+27:
1629                                 vc_state = ESsquare;
1630                                 continue;
1631                 }
1632                 switch(vc_state) {
1633                         case ESesc:
1634                                 vc_state = ESnormal;
1635                                 switch (c) {
1636                                   case '[':
1637                                         vc_state = ESsquare;
1638                                         continue;
1639                                   case '%':
1640                                         vc_state = ESpercent;
1641                                         continue;
1642                                   case 'E':
1643                                         cr(currcons);
1644                                         lf(currcons);
1645                                         continue;
1646                                   case 'M':
1647                                         ri(currcons);
1648                                         continue;
1649                                   case 'D':
1650                                         lf(currcons);
1651                                         continue;
1652                                   case 'H':
1653                                         tab_stop[x >> 5] |= (1 << (x & 31));
1654                                         continue;
1655                                   case 'Z':
1656                                         respond_ID(currcons,tty);
1657                                         continue;
1658                                   case '7':
1659                                         save_cur(currcons);
1660                                         continue;
1661                                   case '8':
1662                                         restore_cur(currcons);
1663                                         continue;
1664                                   case '(':
1665                                         vc_state = ESsetG0;
1666                                         continue;
1667                                   case ')':
1668                                         vc_state = ESsetG1;
1669                                         continue;
1670                                   case '#':
1671                                         vc_state = EShash;
1672                                         continue;
1673                                   case 'c':
1674                                         reset_terminal(currcons,1);
1675                                         continue;
1676                                   case '>':  /* Numeric keypad */
1677                                         clr_kbd(kbdapplic);
1678                                         continue;
1679                                   case '=':  /* Appl. keypad */
1680                                         set_kbd(kbdapplic);
1681                                         continue;
1682                                 }       
1683                                 continue;
1684                         case ESsquare:
1685                                 for(npar = 0 ; npar < NPAR ; npar++)
1686                                         par[npar] = 0;
1687                                 npar = 0;
1688                                 vc_state = ESgetpars;
1689                                 if (c == '[') { /* Function key */
1690                                         vc_state=ESfunckey;
1691                                         continue;
1692                                 }
1693                                 ques = (c=='?');
1694                                 if (ques)
1695                                         continue;
1696                         case ESgetpars:
1697                                 if (c==';' && npar<NPAR-1) {
1698                                         npar++;
1699                                         continue;
1700                                 } else if (c>='0' && c<='9') {
1701                                         par[npar] *= 10;
1702                                         par[npar] += c-'0';
1703                                         continue;
1704                                 } else vc_state=ESgotpars;
1705                         case ESgotpars:
1706                                 vc_state = ESnormal;
1707                                 switch(c) {
1708                                         case 'h':
1709                                                 set_mode(currcons,1);
1710                                                 continue;
1711                                         case 'l':
1712                                                 set_mode(currcons,0);
1713                                                 continue;
1714                                         case 'n':
1715                                                 if (!ques)
1716                                                         if (par[0] == 5)
1717                                                                 status_report(currcons,tty);
1718                                                         else if (par[0] == 6)
1719                                                                 cursor_report(currcons,tty);
1720                                                 continue;
1721                                 }
1722                                 if (ques) {
1723                                         ques = 0;
1724                                         continue;
1725                                 }
1726                                 switch(c) {
1727                                         case 'G': case '`':
1728                                                 if (par[0]) par[0]--;
1729                                                 gotoxy(currcons,par[0],y);
1730                                                 continue;
1731                                         case 'A':
1732                                                 if (!par[0]) par[0]++;
1733                                                 gotoxy(currcons,x,y-par[0]);
1734                                                 continue;
1735                                         case 'B': case 'e':
1736                                                 if (!par[0]) par[0]++;
1737                                                 gotoxy(currcons,x,y+par[0]);
1738                                                 continue;
1739                                         case 'C': case 'a':
1740                                                 if (!par[0]) par[0]++;
1741                                                 gotoxy(currcons,x+par[0],y);
1742                                                 continue;
1743                                         case 'D':
1744                                                 if (!par[0]) par[0]++;
1745                                                 gotoxy(currcons,x-par[0],y);
1746                                                 continue;
1747                                         case 'E':
1748                                                 if (!par[0]) par[0]++;
1749                                                 gotoxy(currcons,0,y+par[0]);
1750                                                 continue;
1751                                         case 'F':
1752                                                 if (!par[0]) par[0]++;
1753                                                 gotoxy(currcons,0,y-par[0]);
1754                                                 continue;
1755                                         case 'd':
1756                                                 if (par[0]) par[0]--;
1757                                                 gotoxy(currcons,x,par[0]);
1758                                                 continue;
1759                                         case 'H': case 'f':
1760                                                 if (par[0]) par[0]--;
1761                                                 if (par[1]) par[1]--;
1762                                                 gotoxy(currcons,par[1],par[0]);
1763                                                 continue;
1764                                         case 'J':
1765                                                 csi_J(currcons,par[0]);
1766                                                 continue;
1767                                         case 'K':
1768                                                 csi_K(currcons,par[0]);
1769                                                 continue;
1770                                         case 'L':
1771                                                 csi_L(currcons,par[0]);
1772                                                 continue;
1773                                         case 'M':
1774                                                 csi_M(currcons,par[0]);
1775                                                 continue;
1776                                         case 'P':
1777                                                 csi_P(currcons,par[0]);
1778                                                 continue;
1779                                         case 'c':
1780                                                 if (!par[0])
1781                                                         respond_ID(currcons,tty);
1782                                                 continue;
1783                                         case 'g':
1784                                                 if (!par[0])
1785                                                         tab_stop[x >> 5] &= ~(1 << (x & 31));
1786                                                 else if (par[0] == 3) {
1787                                                         tab_stop[0] =
1788                                                         tab_stop[1] =
1789                                                         tab_stop[2] =
1790                                                         tab_stop[3] =
1791                                                         tab_stop[4] = 0;
1792                                                 }
1793                                                 continue;
1794                                         case 'm':
1795                                                 csi_m(currcons);
1796                                                 continue;
1797                                         case 'q': /* DECLL - but only 3 leds */
1798                                                 /* map 0,1,2,3 to 0,1,2,4 */
1799                                                 if (par[0] < 4)
1800                                                   setledstate(kbd_table + currcons,
1801                                                               (par[0] < 3) ? par[0] : 4);
1802                                                 continue;
1803                                         case 'r':
1804                                                 if (!par[0])
1805                                                         par[0]++;
1806                                                 if (!par[1])
1807                                                         par[1] = video_num_lines;
1808                                                 /* Minimum allowed region is 2 lines */
1809                                                 if (par[0] < par[1] &&
1810                                                     par[1] <= video_num_lines) {
1811                                                         top=par[0]-1;
1812                                                         bottom=par[1];
1813                                                         gotoxy(currcons,0,0);
1814                                                 }
1815                                                 continue;
1816                                         case 's':
1817                                                 save_cur(currcons);
1818                                                 continue;
1819                                         case 'u':
1820                                                 restore_cur(currcons);
1821                                                 continue;
1822                                         case 'X':
1823                                                 csi_X(currcons, par[0]);
1824                                                 continue;
1825                                         case '@':
1826                                                 csi_at(currcons,par[0]);
1827                                                 continue;
1828                                         case ']': /* setterm functions */
1829                                                 setterm_command(currcons);
1830                                                 continue;
1831                                 }
1832                                 continue;
1833                         case ESpercent:
1834                                 vc_state = ESnormal;
1835                                 switch (c) {
1836                                   case '@':  /* defined in ISO 2022 */
1837                                         utf = 0;
1838                                         continue;
1839                                   case '8':
1840                                         /* ISO/ECMA hasn't yet registered an
1841                                            official ESC sequence for UTF-8,
1842                                            so this one (ESC %8) will likely
1843                                            change in the future. */
1844                                         utf = 1;
1845                                         continue;
1846                                 }
1847                                 continue;
1848                         case ESfunckey:
1849                                 vc_state = ESnormal;
1850                                 continue;
1851                         case EShash:
1852                                 vc_state = ESnormal;
1853                                 if (c == '8') {
1854                                         /* DEC screen alignment test. kludge :-) */
1855                                         video_erase_char =
1856                                                 (video_erase_char & 0xff00) | 'E';
1857                                         csi_J(currcons, 2);
1858                                         video_erase_char =
1859                                                 (video_erase_char & 0xff00) | ' ';
1860                                 }
1861                                 continue;
1862                         case ESsetG0:
1863                                 if (c == '0')
1864                                         G0_charset = GRAF_TRANS;
1865                                 else if (c == 'B')
1866                                         G0_charset = NORM_TRANS;
1867                                 else if (c == 'U')
1868                                         G0_charset = NULL_TRANS;
1869                                 else if (c == 'K')
1870                                         G0_charset = USER_TRANS;
1871                                 if (charset == 0)
1872                                         translate = G0_charset;
1873                                 vc_state = ESnormal;
1874                                 continue;
1875                         case ESsetG1:
1876                                 if (c == '0')
1877                                         G1_charset = GRAF_TRANS;
1878                                 else if (c == 'B')
1879                                         G1_charset = NORM_TRANS;
1880                                 else if (c == 'U')
1881                                         G1_charset = NULL_TRANS;
1882                                 else if (c == 'K')
1883                                         G1_charset = USER_TRANS;
1884                                 if (charset == 1)
1885                                         translate = G1_charset;
1886                                 vc_state = ESnormal;
1887                                 continue;
1888                         default:
1889                                 vc_state = ESnormal;
1890                 }
1891         }
1892         if (vcmode != KD_GRAPHICS)
1893                 set_cursor(currcons);
1894         enable_bh(KEYBOARD_BH);
1895         return n;
1896 }
1897 
1898 static int con_write_room(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
1899 {
1900         if (tty->stopped)
1901                 return 0;
1902         return 4096;            /* No limit, really; we're not buffering */
1903 }
1904 
1905 static int con_chars_in_buffer(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
1906 {
1907         return 0;               /* we're not buffering */
1908 }
1909 
1910 void poke_blanked_console(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1911 {
1912         timer_active &= ~(1<<BLANK_TIMER);
1913         if (vt_cons[fg_console]->vc_mode == KD_GRAPHICS)
1914                 return;
1915         if (console_blanked) {
1916                 timer_table[BLANK_TIMER].expires = 0;
1917                 timer_active |= 1<<BLANK_TIMER;
1918         } else if (blankinterval) {
1919                 timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
1920                 timer_active |= 1<<BLANK_TIMER;
1921         }
1922 }
1923 
1924 void console_print(const char * b)
     /* [previous][next][first][last][top][bottom][index][help] */
1925 {
1926         int currcons = fg_console;
1927         unsigned char c;
1928 
1929         if (!printable)
1930                 return;  /* console not yet initialized */
1931 
1932         if (!vc_cons_allocated(currcons)) {
1933                 /* impossible */
1934                 printk("console_print: tty %d not allocated ??\n", currcons+1);
1935                 return;
1936         }
1937 
1938         while ((c = *(b++)) != 0) {
1939                 if (c == 10 || c == 13 || need_wrap) {
1940                         if (c != 13)
1941                                 lf(currcons);
1942                         cr(currcons);
1943                         if (c == 10 || c == 13)
1944                                 continue;
1945                 }
1946                 *(unsigned short *) pos = (attr << 8) + c;
1947                 if (x == video_num_columns - 1) {
1948                         need_wrap = 1;
1949                         continue;
1950                 }
1951                 x++;
1952                 pos+=2;
1953         }
1954         set_cursor(currcons);
1955         if (vt_cons[fg_console]->vc_mode == KD_GRAPHICS)
1956                 return;
1957         timer_active &= ~(1<<BLANK_TIMER);
1958         if (console_blanked) {
1959                 timer_table[BLANK_TIMER].expires = 0;
1960                 timer_active |= 1<<BLANK_TIMER;
1961         } else if (blankinterval) {
1962                 timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
1963                 timer_active |= 1<<BLANK_TIMER;
1964         }
1965 }
1966 
1967 /*
1968  * con_throttle and con_unthrottle are only used for
1969  * paste_selection(), which has to stuff in a large number of
1970  * characters...
1971  */
1972 static void con_throttle(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
1973 {
1974 }
1975 
1976 static void con_unthrottle(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
1977 {
1978         struct vt_struct *vt = (struct vt_struct *) tty->driver_data;
1979 
1980         wake_up_interruptible(&vt->paste_wait);
1981 }
1982 
1983 static void vc_init(unsigned int currcons, unsigned long rows, unsigned long cols, int do_clear)
     /* [previous][next][first][last][top][bottom][index][help] */
1984 {
1985         long base = (long) vc_scrbuf[currcons];
1986 
1987         video_num_columns = cols;
1988         video_num_lines = rows;
1989         video_size_row = cols<<1;
1990         video_screen_size = video_num_lines * video_size_row;
1991 
1992         pos = origin = video_mem_start = base;
1993         scr_end = base + video_screen_size;
1994         video_mem_end = base + video_screen_size;
1995         reset_vc(currcons);
1996         def_color       = 0x07;   /* white */
1997         ulcolor         = 0x0f;   /* bold white */
1998         halfcolor       = 0x08;   /* grey */
1999         vt_cons[currcons]->paste_wait = 0;
2000         reset_terminal(currcons, do_clear);
2001 }
2002 
2003 static void con_setsize(unsigned long rows, unsigned long cols)
     /* [previous][next][first][last][top][bottom][index][help] */
2004 {
2005         video_num_lines = rows;
2006         video_num_columns = cols;
2007         video_size_row = 2 * cols;
2008         video_screen_size = video_num_lines * video_size_row;
2009 }
2010 
2011 /*
2012  *  long con_init(long);
2013  *
2014  * This routine initializes console interrupts, and does nothing
2015  * else. If you want the screen to clear, call tty_write with
2016  * the appropriate escape-sequence.
2017  *
2018  * Reads the information preserved by setup.s to determine the current display
2019  * type and sets everything accordingly.
2020  */
2021 long con_init(long kmem_start)
     /* [previous][next][first][last][top][bottom][index][help] */
2022 {
2023         char *display_desc = "????";
2024         int currcons = 0;
2025         int orig_x = ORIG_X;
2026         int orig_y = ORIG_Y;
2027 
2028         memset(&console_driver, 0, sizeof(struct tty_driver));
2029         console_driver.magic = TTY_DRIVER_MAGIC;
2030         console_driver.name = "tty";
2031         console_driver.name_base = 1;
2032         console_driver.major = TTY_MAJOR;
2033         console_driver.minor_start = 1;
2034         console_driver.num = MAX_NR_CONSOLES;
2035         console_driver.type = TTY_DRIVER_TYPE_CONSOLE;
2036         console_driver.init_termios = tty_std_termios;
2037         console_driver.flags = TTY_DRIVER_REAL_RAW;
2038         console_driver.refcount = &console_refcount;
2039         console_driver.table = console_table;
2040         console_driver.termios = console_termios;
2041         console_driver.termios_locked = console_termios_locked;
2042 
2043         console_driver.open = con_open;
2044         console_driver.write = con_write;
2045         console_driver.write_room = con_write_room;
2046         console_driver.chars_in_buffer = con_chars_in_buffer;
2047         console_driver.ioctl = vt_ioctl;
2048         console_driver.stop = con_stop;
2049         console_driver.start = con_start;
2050         console_driver.throttle = con_throttle;
2051         console_driver.unthrottle = con_unthrottle;
2052         
2053         if (tty_register_driver(&console_driver))
2054                 panic("Couldn't register console driver\n");
2055         
2056         con_setsize(ORIG_VIDEO_LINES, ORIG_VIDEO_COLS);
2057         video_page = ORIG_VIDEO_PAGE;                   /* never used */
2058 
2059         timer_table[BLANK_TIMER].fn = blank_screen;
2060         timer_table[BLANK_TIMER].expires = 0;
2061         if (blankinterval) {
2062                 timer_table[BLANK_TIMER].expires = jiffies+blankinterval;
2063                 timer_active |= 1<<BLANK_TIMER;
2064         }
2065         
2066         if (ORIG_VIDEO_MODE == 7)       /* Is this a monochrome display? */
2067         {
2068                 video_mem_base = 0xb0000;
2069                 video_port_reg = 0x3b4;
2070                 video_port_val = 0x3b5;
2071                 if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
2072                 {
2073                         video_type = VIDEO_TYPE_EGAM;
2074                         video_mem_term = 0xb8000;
2075                         display_desc = "EGA+";
2076                 }
2077                 else
2078                 {
2079                         video_type = VIDEO_TYPE_MDA;
2080                         video_mem_term = 0xb2000;
2081                         display_desc = "*MDA";
2082                 }
2083         }
2084         else                            /* If not, it is color. */
2085         {
2086                 can_do_color = 1;
2087                 video_mem_base = 0xb8000;
2088                 video_port_reg  = 0x3d4;
2089                 video_port_val  = 0x3d5;
2090                 if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
2091                 {
2092                         video_type = VIDEO_TYPE_EGAC;
2093                         video_mem_term = 0xc0000;
2094                         display_desc = "EGA+";
2095                 }
2096                 else
2097                 {
2098                         video_type = VIDEO_TYPE_CGA;
2099                         video_mem_term = 0xba000;
2100                         display_desc = "*CGA";
2101                 }
2102         }
2103         
2104         /* Initialize the variables used for scrolling (mostly EGA/VGA) */
2105 
2106         /* Due to kmalloc roundup allocating statically is more efficient -
2107            so provide MIN_NR_CONSOLES for people with very little memory */
2108         for (currcons = 0; currcons < MIN_NR_CONSOLES; currcons++) {
2109                 vc_cons[currcons].d = (struct vc_data *) kmem_start;
2110                 kmem_start += sizeof(struct vc_data);
2111                 vt_cons[currcons] = (struct vt_struct *) kmem_start;
2112                 kmem_start += sizeof(struct vt_struct);
2113                 vc_scrbuf[currcons] = (unsigned short *) kmem_start;
2114                 kmem_start += video_screen_size;
2115                 kmalloced = 0;
2116                 screenbuf_size = video_screen_size;
2117                 vc_init(currcons, video_num_lines, video_num_columns, currcons);
2118         }
2119 
2120         currcons = fg_console = 0;
2121 
2122         video_mem_start = video_mem_base;
2123         video_mem_end = video_mem_term;
2124         origin = video_mem_start;
2125         scr_end = video_mem_start + video_num_lines * video_size_row;
2126         gotoxy(currcons,orig_x,orig_y);
2127         printable = 1;
2128         printk("Console: %s %s %ldx%ld, %d virtual console%s (max %d)\n",
2129                 can_do_color ? "colour" : "mono",
2130                 display_desc,
2131                 video_num_columns,video_num_lines,
2132                 MIN_NR_CONSOLES, (MIN_NR_CONSOLES == 1) ? "" : "s", MAX_NR_CONSOLES);
2133         register_console(console_print);
2134         return kmem_start;
2135 }
2136 
2137 static void get_scrmem(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
2138 {
2139         memcpy((void *)vc_scrbuf[currcons], (void *)origin, video_screen_size);
2140         origin = video_mem_start = (unsigned long)vc_scrbuf[currcons];
2141         scr_end = video_mem_end = video_mem_start + video_screen_size;
2142         pos = origin + y*video_size_row + (x<<1);
2143 }
2144 
2145 static void set_scrmem(int currcons, long offset)
     /* [previous][next][first][last][top][bottom][index][help] */
2146 {
2147 #ifdef CONFIG_HGA
2148   /* This works with XFree86 1.2, 1.3 and 2.0
2149      This code could be extended and made more generally useful if we could
2150      determine the actual video mode. It appears that this should be
2151      possible on a genuine Hercules card, but I (WM) haven't been able to
2152      read from any of the required registers on my clone card.
2153      */
2154         /* This code should work with Hercules and MDA cards. */
2155         if (video_type == VIDEO_TYPE_MDA)
2156           {
2157             if (vcmode == KD_TEXT)
2158               {
2159                 /* Ensure that the card is in text mode. */
2160                 int     i;
2161                 static char herc_txt_tbl[12] = {
2162                   0x61,0x50,0x52,0x0f,0x19,6,0x19,0x19,2,0x0d,0x0b,0x0c };
2163                 outb_p(0, 0x3bf);  /* Back to power-on defaults */
2164                 outb_p(0, 0x3b8);  /* Blank the screen, select page 0, etc */
2165                 for ( i = 0 ; i < 12 ; i++ )
2166                   {
2167                     outb_p(i, 0x3b4);
2168                     outb_p(herc_txt_tbl[i], 0x3b5);
2169                   }
2170               }
2171 #define HGA_BLINKER_ON 0x20
2172 #define HGA_SCREEN_ON  8
2173             /* Make sure that the hardware is not blanked */
2174             outb_p(HGA_BLINKER_ON | HGA_SCREEN_ON, 0x3b8);
2175           }
2176 #endif CONFIG_HGA
2177 
2178         if (video_mem_term - video_mem_base < offset + video_screen_size)
2179           offset = 0;   /* strange ... */
2180         memcpy((void *)(video_mem_base + offset), (void *) origin, video_screen_size);
2181         video_mem_start = video_mem_base;
2182         video_mem_end = video_mem_term;
2183         origin = video_mem_base + offset;
2184         scr_end = origin + video_screen_size;
2185         pos = origin + y*video_size_row + (x<<1);
2186 }
2187 
2188 void blank_screen(void)
     /* [previous][next][first][last][top][bottom][index][help] */
2189 {
2190 #ifndef CONFIG_VESA_PSPM
2191         int currcons;
2192 #endif
2193 
2194         if (console_blanked)
2195                 return;
2196         if (!vc_cons_allocated(fg_console)) {
2197                 /* impossible */
2198                 printk("blank_screen: tty %d not allocated ??\n", fg_console+1);
2199                 return;
2200         }
2201         timer_table[BLANK_TIMER].fn = unblank_screen;
2202 
2203 #ifdef CONFIG_VESA_PSPM
2204         vesa_blank();
2205 #else
2206         /* try not to lose information by blanking, and not to waste memory */
2207         currcons = fg_console;
2208         has_scrolled = 0;
2209         blank__origin = __origin;
2210         blank_origin = origin;
2211         set_origin(fg_console);
2212         get_scrmem(fg_console);
2213         unblank_origin = origin;
2214         memsetw((void *)blank_origin, BLANK, video_mem_term-blank_origin);
2215         hide_cursor();
2216 #endif  
2217         console_blanked = fg_console + 1;
2218 }
2219 
2220 void unblank_screen(void)
     /* [previous][next][first][last][top][bottom][index][help] */
2221 {
2222         int currcons;
2223 #ifndef CONFIG_VESA_PSPM
2224         int resetorg;
2225         long offset;
2226 #endif
2227 
2228         if (!console_blanked)
2229                 return;
2230         if (!vc_cons_allocated(fg_console)) {
2231                 /* impossible */
2232                 printk("unblank_screen: tty %d not allocated ??\n", fg_console+1);
2233                 return;
2234         }
2235         timer_table[BLANK_TIMER].fn = blank_screen;
2236         if (blankinterval) {
2237                 timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
2238                 timer_active |= 1<<BLANK_TIMER;
2239         }
2240         currcons = fg_console;
2241 #ifdef CONFIG_VESA_PSPM
2242         vesa_unblank();
2243         console_blanked=0;
2244 #else
2245         offset = 0;
2246         resetorg = 0;
2247         if (console_blanked == fg_console + 1 && origin == unblank_origin
2248             && !has_scrolled) {
2249                 /* try to restore the exact situation before blanking */
2250                 resetorg = 1;
2251                 offset = (blank_origin - video_mem_base)
2252                         - (unblank_origin - video_mem_start);
2253         }
2254 
2255         console_blanked = 0;
2256         set_scrmem(fg_console, offset);
2257         set_origin(fg_console);
2258         set_cursor(fg_console);
2259         if (resetorg)
2260                 __set_origin(blank__origin);
2261 #endif
2262 }
2263 
2264 void update_screen(int new_console)
     /* [previous][next][first][last][top][bottom][index][help] */
2265 {
2266         static int lock = 0;
2267 
2268         if (new_console == fg_console || lock)
2269                 return;
2270         if (!vc_cons_allocated(new_console)) {
2271                 /* strange ... */
2272                 printk("update_screen: tty %d not allocated ??\n", new_console+1);
2273                 return;
2274         }
2275         lock = 1;
2276 #ifdef CONFIG_SELECTION
2277         clear_selection();
2278 #endif /* CONFIG_SELECTION */
2279         if (!console_blanked)
2280                 get_scrmem(fg_console);
2281         else
2282                 console_blanked = -1;      /* no longer of the form console+1 */
2283         fg_console = new_console; /* this is the only (nonzero) assignment to fg_console */
2284                                   /* consequently, fg_console will always be allocated */
2285         set_scrmem(fg_console, 0); 
2286         set_origin(fg_console);
2287         set_cursor(fg_console);
2288         set_leds();
2289         compute_shiftstate();
2290         lock = 0;
2291 }
2292 
2293 /*
2294  * do_screendump is used for three tasks:
2295  *   if (mode==0) is the old ioctl(TIOCLINUX,0)
2296  *   if (mode==1) dumps wd,hg, cursor position, and all the char-attr pairs
2297  *   if (mode==2) restores what mode1 got.
2298  * the new modes are needed for a fast and complete dump-restore cycle,
2299  * needed to implement root-window menus in text mode (A Rubini Nov 1994)
2300  */
2301 int do_screendump(int arg, int mode)
     /* [previous][next][first][last][top][bottom][index][help] */
2302 {
2303         char *sptr, *buf = (char *)arg;
2304         int currcons, l, chcount;
2305 
2306         if (!suser())
2307                 return -EPERM;
2308         l = verify_area(VERIFY_READ, buf, 2);
2309         if (l)
2310                 return l;
2311         currcons = get_fs_byte(buf+1);
2312         currcons = (currcons ? currcons-1 : fg_console);
2313         if (!vc_cons_allocated(currcons))
2314                 return -EIO;
2315         
2316         /* mode 0 needs 2+wd*ht, modes 1 and 2 need 4+2*wd*ht */
2317         chcount=video_num_columns*video_num_lines;
2318         l = verify_area(mode==2 ? VERIFY_READ :VERIFY_WRITE,
2319                 buf, (2+chcount)*(mode ? 2 : 1));
2320         if (l)
2321                 return l;
2322         if (mode<2) {
2323         put_fs_byte((char)(video_num_lines),buf++);   
2324         put_fs_byte((char)(video_num_columns),buf++);
2325             }
2326         switch(mode) {
2327             case 0:
2328         sptr = (char *) origin;
2329                         for (l=chcount; l>0 ; l--, sptr++)
2330                 put_fs_byte(*sptr++,buf++);     
2331                         break;
2332             case 1:
2333 #ifdef CONFIG_SELECTION
2334                         clear_selection();
2335 #endif
2336                         put_fs_byte((char)x,buf++); put_fs_byte((char)y,buf++); 
2337                         memcpy_tofs(buf,(char *)origin,2*chcount);
2338                         break;
2339             case 2:
2340                         buf+=4; /* ioctl#, console#, x,y */
2341                         memcpy_fromfs((char *)origin,buf,2*chcount);
2342                         break;
2343             }
2344         return(0);
2345 }
2346 
2347 /*
2348  * Allocate the console screen memory.
2349  */
2350 int con_open(struct tty_struct *tty, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
2351 {
2352         unsigned int    idx;
2353         int i;
2354 
2355         idx = MINOR(tty->device) - tty->driver.minor_start;
2356         
2357         i = vc_allocate(idx);
2358         if (i)
2359                 return i;
2360 
2361         vt_cons[idx]->vc_num = idx;
2362         tty->driver_data = vt_cons[idx];
2363         
2364         if (!tty->winsize.ws_row && !tty->winsize.ws_col) {
2365                 tty->winsize.ws_row = video_num_lines;
2366                 tty->winsize.ws_col = video_num_columns;
2367         }
2368         return 0;
2369 }
2370 
2371 #ifdef CONFIG_SELECTION
2372 /* correction factor for when screen is hardware-scrolled */
2373 #define hwscroll_offset (currcons == fg_console ? ((__real_origin - __origin) << 1) : 0)
2374 
2375 /* set reverse video on characters s-e of console with selection. */
2376 static void highlight(const int currcons, const int s, const int e)
     /* [previous][next][first][last][top][bottom][index][help] */
2377 {
2378         unsigned char *p, *p1, *p2;
2379 
2380         p1 = (unsigned char *)origin - hwscroll_offset + s + 1;
2381         p2 = (unsigned char *)origin - hwscroll_offset + e + 1;
2382         if (p1 > p2)
2383         {
2384                 p = p1;
2385                 p1 = p2;
2386                 p2 = p;
2387         }
2388         for (p = p1; p <= p2; p += 2)
2389                 *p = (*p & 0x88) | ((*p << 4) & 0x70) | ((*p >> 4) & 0x07);
2390 }
2391 
2392 /* use complementary color to show the pointer */
2393 static void highlight_pointer(const int currcons, const int where)
     /* [previous][next][first][last][top][bottom][index][help] */
2394 {
2395         unsigned char *p;
2396         static unsigned char *prev=NULL;
2397 
2398         if (where==-1) /* remove the pointer */
2399         {
2400                 if (prev)
2401                 {
2402                         *prev ^= 0x77;
2403                         prev=NULL;
2404                 }
2405         }
2406         else
2407         {
2408                 p = (unsigned char *)origin - hwscroll_offset + where + 1;
2409                 *p ^= 0x77;
2410                 if (prev) *prev ^= 0x77; /* remove the previous one */
2411                 prev=p;
2412         }
2413 }
2414 
2415 
2416 /*
2417  * This function uses a 128-bit look up table
2418  */
2419 static unsigned long inwordLut[4]={
2420   0x00000000, /* control chars     */
2421   0x03FF0000, /* digits            */
2422   0x87FFFFFE, /* uppercase and '_' */
2423   0x07FFFFFE  /* lowercase         */
2424 };
2425 static inline int inword(const char c) {
     /* [previous][next][first][last][top][bottom][index][help] */
2426    return ( inwordLut[(c>>5)&3] >> (c&0x1F) ) & 1;
2427 }
2428 
2429 /* set inwordLut contents. Invoked by ioctl(). */
2430 int sel_loadlut(const int arg)
     /* [previous][next][first][last][top][bottom][index][help] */
2431 {
2432     memcpy_fromfs(inwordLut,(unsigned long *)(arg+4),16);
2433     return 0;
2434 }
2435 
2436 /* does screen address p correspond to character at LH/RH edge of screen? */
2437 static inline int atedge(const int p)
     /* [previous][next][first][last][top][bottom][index][help] */
2438 {
2439         return (!(p % video_size_row) || !((p + 2) % video_size_row));
2440 }
2441 
2442 /* constrain v such that l <= v <= u */
2443 static inline short limit(const int v, const int l, const int u)
     /* [previous][next][first][last][top][bottom][index][help] */
2444 {
2445         return (v < l) ? l : ((v > u) ? u : v);
2446 }
2447 
2448 /* invoked via ioctl(TIOCLINUX) */
2449 int mouse_reporting(void)
     /* [previous][next][first][last][top][bottom][index][help] */
2450 {
2451         int currcons = fg_console;
2452 
2453         return report_mouse;
2454 }
2455 
2456 /* set the current selection. Invoked by ioctl(). */
2457 int set_selection(const int arg, struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
2458 {
2459         unsigned short *args, xs, ys, xe, ye;
2460         int currcons = fg_console;
2461         int sel_mode, new_sel_start, new_sel_end, spc;
2462         char *bp, *obp, *spos;
2463         int i, ps, pe;
2464         char *off = (char *)origin - hwscroll_offset;
2465 
2466         unblank_screen();
2467         args = (unsigned short *)(arg + 1);
2468         xs = get_fs_word(args++) - 1;
2469         ys = get_fs_word(args++) - 1;
2470         xe = get_fs_word(args++) - 1;
2471         ye = get_fs_word(args++) - 1;
2472         sel_mode = get_fs_word(args);
2473 
2474         xs = limit(xs, 0, video_num_columns - 1);
2475         ys = limit(ys, 0, video_num_lines - 1);
2476         xe = limit(xe, 0, video_num_columns - 1);
2477         ye = limit(ye, 0, video_num_lines - 1);
2478         ps = ys * video_size_row + (xs << 1);
2479         pe = ye * video_size_row + (xe << 1);
2480 
2481         if (report_mouse && (sel_mode & 16)) {
2482                 mouse_report(currcons, tty, sel_mode & 15, xs, ys);
2483                 return 0;
2484         }
2485 
2486         if (ps > pe)    /* make sel_start <= sel_end */
2487         {
2488                 int tmp = ps;
2489                 ps = pe;
2490                 pe = tmp;
2491         }
2492 
2493         switch (sel_mode)
2494         {
2495                 case 0: /* character-by-character selection */
2496                         new_sel_start = ps;
2497                         new_sel_end = pe;
2498                         break;
2499                 case 1: /* word-by-word selection */
2500                         spc = isspace(*(off + ps));
2501                         for (new_sel_start = ps; ; ps -= 2)
2502                         {
2503                                 if ((spc && !isspace(*(off + ps))) ||
2504                                     (!spc && !inword(*(off + ps))))
2505                                         break;
2506                                 new_sel_start = ps;
2507                                 if (!(ps % video_size_row))
2508                                         break;
2509                         }
2510                         spc = isspace(*(off + pe));
2511                         for (new_sel_end = pe; ; pe += 2)
2512                         {
2513                                 if ((spc && !isspace(*(off + pe))) ||
2514                                     (!spc && !inword(*(off + pe))))
2515                                         break;
2516                                 new_sel_end = pe;
2517                                 if (!((pe + 2) % video_size_row))
2518                                         break;
2519                         }
2520                         break;
2521                 case 2: /* line-by-line selection */
2522                         new_sel_start = ps - ps % video_size_row;
2523                         new_sel_end = pe + video_size_row
2524                                     - pe % video_size_row - 2;
2525                         break;
2526                 case 3: /* pointer highlight */
2527                         if (sel_cons != currcons)
2528                         {
2529                                 clear_selection();
2530                                 sel_cons = currcons;
2531                         }
2532                         highlight_pointer(sel_cons,pe);
2533                         return 0; /* nothing more */
2534                 default:
2535                         return -EINVAL;
2536         }
2537         /* remove the pointer */
2538         highlight_pointer(sel_cons,-1);
2539         /* select to end of line if on trailing space */
2540         if (new_sel_end > new_sel_start &&
2541                 !atedge(new_sel_end) && isspace(*(off + new_sel_end)))
2542         {
2543                 for (pe = new_sel_end + 2; ; pe += 2)
2544                 {
2545                         if (!isspace(*(off + pe)) || atedge(pe))
2546                                 break;
2547                 }
2548                 if (isspace(*(off + pe)))
2549                         new_sel_end = pe;
2550         }
2551         if (sel_cons != currcons)
2552         {
2553                 clear_selection();
2554                 sel_cons = currcons;
2555         }
2556         if (sel_start == -1)    /* no current selection */
2557                 highlight(sel_cons, new_sel_start, new_sel_end);
2558         else if (new_sel_start == sel_start)
2559         {
2560                 if (new_sel_end == sel_end)     /* no action required */
2561                         return 0;
2562                 else if (new_sel_end > sel_end) /* extend to right */
2563                         highlight(sel_cons, sel_end + 2, new_sel_end);
2564                 else                            /* contract from right */
2565                         highlight(sel_cons, new_sel_end + 2, sel_end);
2566         }
2567         else if (new_sel_end == sel_end)
2568         {
2569                 if (new_sel_start < sel_start)  /* extend to left */
2570                         highlight(sel_cons, new_sel_start, sel_start - 2);
2571                 else                            /* contract from left */
2572                         highlight(sel_cons, sel_start, new_sel_start - 2);
2573         }
2574         else    /* some other case; start selection from scratch */
2575         {
2576                 clear_selection();
2577                 highlight(sel_cons, new_sel_start, new_sel_end);
2578         }
2579         sel_start = new_sel_start;
2580         sel_end = new_sel_end;
2581         obp = bp = sel_buffer;
2582         for (i = sel_start; i <= sel_end; i += 2)
2583         {
2584                 spos = (char *)off + i;
2585                 *bp++ = *spos;
2586                 if (!isspace(*spos))
2587                         obp = bp;
2588                 if (! ((i + 2) % video_size_row))
2589                 {
2590                         /* strip trailing blanks from line and add newline,
2591                            unless non-space at end of line. */
2592                         if (obp != bp)
2593                         {
2594                                 bp = obp;
2595                                 *bp++ = '\r';
2596                         }
2597                         obp = bp;
2598                 }
2599                 /* check for space, leaving room for next character, possible
2600                    newline, and null at end. */
2601                 if (bp - sel_buffer > SEL_BUFFER_SIZE - 3)
2602                         break;
2603         }
2604         *bp = '\0';
2605         return 0;
2606 }
2607 
2608 /* insert the contents of the selection buffer into the queue of the
2609    tty associated with the current console. Invoked by ioctl(). */
2610 int paste_selection(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
2611 {
2612         struct wait_queue wait = { current, NULL };
2613         char    *bp = sel_buffer;
2614         int     c, l;
2615         struct vt_struct *vt = (struct vt_struct *) tty->driver_data;
2616         
2617         if (!sel_buffer[0])
2618                 return 0;
2619         unblank_screen();
2620         c = strlen(sel_buffer);
2621         current->state = TASK_INTERRUPTIBLE;
2622         add_wait_queue(&vt->paste_wait, &wait);
2623         while (c) {
2624                 if (test_bit(TTY_THROTTLED, &tty->flags)) {
2625                         schedule();
2626                         continue;
2627                 }
2628                 l = MIN(c, tty->ldisc.receive_room(tty));
2629                 tty->ldisc.receive_buf(tty, bp, 0, l);
2630                 c -= l;
2631                 bp += l;
2632         }
2633         current->state = TASK_RUNNING;
2634         return 0;
2635 }
2636 
2637 /* remove the current selection highlight, if any, from the console holding
2638    the selection. */
2639 static void clear_selection()
     /* [previous][next][first][last][top][bottom][index][help] */
2640 {
2641         highlight_pointer(sel_cons, -1); /* hide the pointer */
2642         if (sel_start != -1)
2643         {
2644                 highlight(sel_cons, sel_start, sel_end);
2645                 sel_start = -1;
2646         }
2647 }
2648 #endif /* CONFIG_SELECTION */
2649 
2650 /*
2651  * PIO_FONT support.
2652  *
2653  * The font loading code goes back to the codepage package by
2654  * Joel Hoffman (joel@wam.umd.edu). (He reports that the original
2655  * reference is: "From: p. 307 of _Programmer's Guide to PC & PS/2
2656  * Video Systems_ by Richard Wilton. 1987.  Microsoft Press".)
2657  *
2658  * Change for certain monochrome monitors by Yury Shevchuck
2659  * (sizif@botik.yaroslavl.su).
2660  */
2661 
2662 #define colourmap ((char *)0xa0000)
2663 /* Pauline Middelink <middelin@polyware.iaf.nl> reports that we
2664    should use 0xA0000 for the bwmap as well.. */
2665 #define blackwmap ((char *)0xa0000)
2666 #define cmapsz 8192
2667 #define seq_port_reg (0x3c4)
2668 #define seq_port_val (0x3c5)
2669 #define gr_port_reg (0x3ce)
2670 #define gr_port_val (0x3cf)
2671 
2672 static int set_get_font(char * arg, int set)
     /* [previous][next][first][last][top][bottom][index][help] */
2673 {
2674 #ifdef CAN_LOAD_EGA_FONTS
2675         int i;
2676         char *charmap;
2677         int beg;
2678 
2679         /* no use to "load" CGA... */
2680 
2681         if (video_type == VIDEO_TYPE_EGAC) {
2682                 charmap = colourmap;
2683                 beg = 0x0e;
2684         } else if (video_type == VIDEO_TYPE_EGAM) {
2685                 charmap = blackwmap;
2686                 beg = 0x0a;
2687         } else
2688                 return -EINVAL;
2689 
2690         i = verify_area(set ? VERIFY_READ : VERIFY_WRITE, (void *)arg, cmapsz);
2691         if (i)
2692                 return i;
2693 
2694         cli();
2695         outb_p( 0x00, seq_port_reg );   /* First, the sequencer */
2696         outb_p( 0x01, seq_port_val );   /* Synchronous reset */
2697         outb_p( 0x02, seq_port_reg );
2698         outb_p( 0x04, seq_port_val );   /* CPU writes only to map 2 */
2699         outb_p( 0x04, seq_port_reg );
2700         outb_p( 0x07, seq_port_val );   /* Sequential addressing */
2701         outb_p( 0x00, seq_port_reg );
2702         outb_p( 0x03, seq_port_val );   /* Clear synchronous reset */
2703 
2704         outb_p( 0x04, gr_port_reg );    /* Now, the graphics controller */
2705         outb_p( 0x02, gr_port_val );    /* select map 2 */
2706         outb_p( 0x05, gr_port_reg );
2707         outb_p( 0x00, gr_port_val );    /* disable odd-even addressing */
2708         outb_p( 0x06, gr_port_reg );
2709         outb_p( 0x00, gr_port_val );    /* map start at A000:0000 */
2710         sti();
2711 
2712         if (set)
2713                 for (i=0; i<cmapsz ; i++)
2714                         *(charmap+i) = get_fs_byte(arg+i);
2715         else
2716                 for (i=0; i<cmapsz ; i++)
2717                         put_fs_byte(*(charmap+i), arg+i);
2718 
2719         cli();
2720         outb_p( 0x00, seq_port_reg );   /* First, the sequencer */
2721         outb_p( 0x01, seq_port_val );   /* Synchronous reset */
2722         outb_p( 0x02, seq_port_reg );
2723         outb_p( 0x03, seq_port_val );   /* CPU writes to maps 0 and 1 */
2724         outb_p( 0x04, seq_port_reg );
2725         outb_p( 0x03, seq_port_val );   /* odd-even addressing */
2726         outb_p( 0x00, seq_port_reg );
2727         outb_p( 0x03, seq_port_val );   /* clear synchronous reset */
2728 
2729         outb_p( 0x04, gr_port_reg );    /* Now, the graphics controller */
2730         outb_p( 0x00, gr_port_val );    /* select map 0 for CPU */
2731         outb_p( 0x05, gr_port_reg );
2732         outb_p( 0x10, gr_port_val );    /* enable even-odd addressing */
2733         outb_p( 0x06, gr_port_reg );
2734         outb_p( beg, gr_port_val );     /* map starts at b800:0 or b000:0 */
2735         sti();
2736 
2737         return 0;
2738 #else
2739         return -EINVAL;
2740 #endif
2741 }
2742 
2743 /*
2744  * Load font into the EGA/VGA character generator. arg points to a 8192
2745  * byte map, 32 bytes per character. Only first H of them are used for
2746  * 8xH fonts (0 < H <= 32).
2747  */
2748 
2749 int con_set_font (char *arg)
     /* [previous][next][first][last][top][bottom][index][help] */
2750 {
2751         return set_get_font (arg,1);
2752 }
2753 
2754 int con_get_font (char *arg)
     /* [previous][next][first][last][top][bottom][index][help] */
2755 {
2756         return set_get_font (arg,0);
2757 }
2758 
2759 /*
2760  * Load customizable translation table (USER_TRANS[]). All checks are here,
2761  * so we need only include 'return con_set_trans(arg)' in the ioctl handler
2762  * arg points to a 256 byte translation table.
2763  */
2764 int con_set_trans(char * arg)
     /* [previous][next][first][last][top][bottom][index][help] */
2765 {
2766         int i;
2767 
2768         i = verify_area(VERIFY_READ, (void *)arg, E_TABSZ);
2769         if (i)
2770                 return i;
2771 
2772         for (i=0; i<E_TABSZ ; i++) USER_TRANS[i] = get_fs_byte(arg+i);
2773         USER_TRANS[012]=0;
2774         USER_TRANS[014]=0;
2775         USER_TRANS[015]=0;
2776         USER_TRANS[033]=0;
2777         return 0;
2778 }
2779 
2780 int con_get_trans(char * arg)
     /* [previous][next][first][last][top][bottom][index][help] */
2781 {
2782         int i;
2783 
2784         i = verify_area(VERIFY_WRITE, (void *)arg, E_TABSZ);
2785         if (i)
2786                 return i;
2787 
2788         for (i=0; i<E_TABSZ ; i++) put_fs_byte(USER_TRANS[i],arg+i);
2789         return 0;
2790 }

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