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

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