root/drivers/char/console.c

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

DEFINITIONS

This source file includes following definitions.
  1. gotoxy
  2. __set_origin
  3. scrollback
  4. scrollfront
  5. set_origin
  6. hide_cursor
  7. set_cursor
  8. scrup
  9. scrdown
  10. lf
  11. ri
  12. cr
  13. bs
  14. del
  15. csi_J
  16. csi_K
  17. update_attr
  18. default_attr
  19. csi_m
  20. respond_string
  21. respond_num
  22. cursor_report
  23. status_report
  24. respond_ID
  25. invert_screen
  26. set_mode
  27. setterm_command
  28. insert_char
  29. insert_line
  30. delete_char
  31. delete_line
  32. csi_at
  33. csi_L
  34. csi_P
  35. csi_M
  36. save_cur
  37. restore_cur
  38. reset_terminal
  39. con_write
  40. do_keyboard_interrupt
  41. memsetw
  42. console_print
  43. con_init
  44. kbdsave
  45. get_scrmem
  46. set_scrmem
  47. blank_screen
  48. unblank_screen
  49. update_screen
  50. do_screendump
  51. con_open
  52. highlight
  53. inword
  54. atedge
  55. limit
  56. set_selection
  57. paste_selection
  58. clear_selection
  59. set_get_font
  60. con_set_font
  61. con_get_font
  62. con_set_trans
  63. con_get_trans

   1 /*
   2  *  linux/kernel/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  *      'long con_init(long)'
  13  *      'int con_open(struct tty_struct *tty, struct file * filp)'
  14  *      'void update_screen(int new_console)'
  15  *      'void blank_screen(void)'
  16  *      'void unblank_screen(void)'
  17  *
  18  *      'int  con_get_font(char *)' 
  19  *      'int  con_set_font(char *)' 
  20  *      'int  con_get_trans(char *)'
  21  *      'int  con_set_trans(char *)'
  22  * 
  23  * Hopefully this will be a rather complete VT102 implementation.
  24  *
  25  * Beeping thanks to John T Kohl.
  26  * 
  27  * Virtual Consoles, Screen Blanking, Screen Dumping, Color, Graphics
  28  *   Chars, and VT100 enhancements by Peter MacDonald.
  29  *
  30  * Copy and paste function by Andrew Haylett.
  31  *
  32  * User definable mapping table and font loading by Eugene G. Crosser,
  33  * <crosser@pccross.msk.su>
  34  *
  35  * Code to check for different video-cards mostly by Galen Hunt,
  36  * <g-hunt@ee.utah.edu>
  37  *
  38  */
  39 
  40 #define CAN_LOAD_EGA_FONTS    /* undefine if the user must not do this */
  41 
  42 /*
  43  *  NOTE!!! We sometimes disable and enable interrupts for a short while
  44  * (to put a word in video IO), but this will work even for keyboard
  45  * interrupts. We know interrupts aren't enabled when getting a keyboard
  46  * interrupt, as we use trap-gates. Hopefully all is well.
  47  */
  48 
  49 #include <linux/sched.h>
  50 #include <linux/timer.h>
  51 #include <linux/tty.h>
  52 #include <linux/config.h>
  53 #include <linux/kernel.h>
  54 #include <linux/string.h>
  55 #include <linux/errno.h>
  56 #include <linux/kd.h>
  57 
  58 #include <asm/io.h>
  59 #include <asm/system.h>
  60 #include <asm/segment.h>
  61 
  62 #include "kbd_kern.h"
  63 #include "vt_kern.h"
  64 
  65 #ifdef CONFIG_SELECTION
  66 #include <linux/ctype.h>
  67 
  68 /* Routines for selection control. */
  69 int set_selection(const int arg);
  70 int paste_selection(struct tty_struct *tty);
  71 static void clear_selection(void);
  72 
  73 /* Variables for selection control. */
  74 #define SEL_BUFFER_SIZE TTY_BUF_SIZE
  75 static int sel_cons;
  76 static int sel_start = -1;
  77 static int sel_end;
  78 static char sel_buffer[SEL_BUFFER_SIZE] = { '\0' };
  79 #endif /* CONFIG_SELECTION */
  80 
  81 #define NPAR 16
  82 
  83 extern void vt_init(void);
  84 extern void register_console(void (*proc)(const char *));
  85 extern void compute_shiftstate(void);
  86 
  87 unsigned long   video_num_columns;              /* Number of text columns       */
  88 unsigned long   video_num_lines;                /* Number of text lines         */
  89 
  90 static unsigned char    video_type;             /* Type of display being used   */
  91 static unsigned long    video_mem_base;         /* Base of video memory         */
  92 static unsigned long    video_mem_term;         /* End of video memory          */
  93 static unsigned long    video_size_row;         /* Bytes per row                */
  94 static unsigned char    video_page;             /* Initial video page           */
  95 static unsigned short   video_port_reg;         /* Video register select port   */
  96 static unsigned short   video_port_val;         /* Video register value port    */
  97 static int can_do_color = 0;
  98 static int printable = 0;
  99 
 100 static struct {
 101         unsigned short  vc_video_erase_char;    /* Background erase character */
 102         unsigned char   vc_attr;                /* Current attributes */
 103         unsigned char   vc_def_color;           /* Default colors */
 104         unsigned char   vc_color;               /* Foreground & background */
 105         unsigned char   vc_s_color;             /* Saved foreground & background */
 106         unsigned char   vc_ulcolor;             /* Colour for underline mode */
 107         unsigned char   vc_halfcolor;           /* Colour for half intensity mode */
 108         unsigned long   vc_origin;              /* Used for EGA/VGA fast scroll */
 109         unsigned long   vc_scr_end;             /* Used for EGA/VGA fast scroll */
 110         unsigned long   vc_pos;
 111         unsigned long   vc_x,vc_y;
 112         unsigned long   vc_top,vc_bottom;
 113         unsigned long   vc_state;
 114         unsigned long   vc_npar,vc_par[NPAR];
 115         unsigned long   vc_video_mem_start;     /* Start of video RAM           */
 116         unsigned long   vc_video_mem_end;       /* End of video RAM (sort of)   */
 117         unsigned long   vc_saved_x;
 118         unsigned long   vc_saved_y;
 119         /* mode flags */
 120         unsigned long   vc_charset      : 1;    /* Character set G0 / G1 */
 121         unsigned long   vc_s_charset    : 1;    /* Saved character set */
 122         unsigned long   vc_decscnm      : 1;    /* Screen Mode */
 123         unsigned long   vc_decom        : 1;    /* Origin Mode */
 124         unsigned long   vc_decawm       : 1;    /* Autowrap Mode */
 125         unsigned long   vc_deccm        : 1;    /* Cursor Visible */
 126         unsigned long   vc_decim        : 1;    /* Insert Mode */
 127         /* attribute flags */
 128         unsigned long   vc_intensity    : 2;    /* 0=half-bright, 1=normal, 2=bold */
 129         unsigned long   vc_underline    : 1;
 130         unsigned long   vc_blink        : 1;
 131         unsigned long   vc_reverse      : 1;
 132         unsigned long   vc_s_intensity  : 2;    /* saved rendition */
 133         unsigned long   vc_s_underline  : 1;
 134         unsigned long   vc_s_blink      : 1;
 135         unsigned long   vc_s_reverse    : 1;
 136         /* misc */
 137         unsigned long   vc_ques         : 1;
 138         unsigned long   vc_need_wrap    : 1;
 139         unsigned long   vc_tab_stop[5];         /* Tab stops. 160 columns. */
 140         unsigned char * vc_translate;
 141         unsigned char * vc_G0_charset;
 142         unsigned char * vc_G1_charset;
 143         unsigned char * vc_saved_G0;
 144         unsigned char * vc_saved_G1;
 145         /* additional information is in vt_kern.h */
 146 } vc_cons [NR_CONSOLES];
 147 
 148 unsigned short *vc_scrbuf[NR_CONSOLES];
 149 static unsigned short * vc_scrmembuf;
 150 static int console_blanked = 0;
 151 
 152 #define origin          (vc_cons[currcons].vc_origin)
 153 #define scr_end         (vc_cons[currcons].vc_scr_end)
 154 #define pos             (vc_cons[currcons].vc_pos)
 155 #define top             (vc_cons[currcons].vc_top)
 156 #define bottom          (vc_cons[currcons].vc_bottom)
 157 #define x               (vc_cons[currcons].vc_x)
 158 #define y               (vc_cons[currcons].vc_y)
 159 #define state           (vc_cons[currcons].vc_state)
 160 #define npar            (vc_cons[currcons].vc_npar)
 161 #define par             (vc_cons[currcons].vc_par)
 162 #define ques            (vc_cons[currcons].vc_ques)
 163 #define attr            (vc_cons[currcons].vc_attr)
 164 #define saved_x         (vc_cons[currcons].vc_saved_x)
 165 #define saved_y         (vc_cons[currcons].vc_saved_y)
 166 #define translate       (vc_cons[currcons].vc_translate)
 167 #define G0_charset      (vc_cons[currcons].vc_G0_charset)
 168 #define G1_charset      (vc_cons[currcons].vc_G1_charset)
 169 #define saved_G0        (vc_cons[currcons].vc_saved_G0)
 170 #define saved_G1        (vc_cons[currcons].vc_saved_G1)
 171 #define video_mem_start (vc_cons[currcons].vc_video_mem_start)
 172 #define video_mem_end   (vc_cons[currcons].vc_video_mem_end)
 173 #define video_erase_char (vc_cons[currcons].vc_video_erase_char)        
 174 #define decscnm         (vc_cons[currcons].vc_decscnm)
 175 #define decom           (vc_cons[currcons].vc_decom)
 176 #define decawm          (vc_cons[currcons].vc_decawm)
 177 #define deccm           (vc_cons[currcons].vc_deccm)
 178 #define decim           (vc_cons[currcons].vc_decim)
 179 #define need_wrap       (vc_cons[currcons].vc_need_wrap)
 180 #define color           (vc_cons[currcons].vc_color)
 181 #define s_color         (vc_cons[currcons].vc_s_color)
 182 #define def_color       (vc_cons[currcons].vc_def_color)
 183 #define foreground      (color & 0x0f)
 184 #define background      (color & 0xf0)
 185 #define charset         (vc_cons[currcons].vc_charset)
 186 #define s_charset       (vc_cons[currcons].vc_s_charset)
 187 #define intensity       (vc_cons[currcons].vc_intensity)
 188 #define underline       (vc_cons[currcons].vc_underline)
 189 #define blink           (vc_cons[currcons].vc_blink)
 190 #define reverse         (vc_cons[currcons].vc_reverse)
 191 #define s_intensity     (vc_cons[currcons].vc_s_intensity)
 192 #define s_underline     (vc_cons[currcons].vc_s_underline)
 193 #define s_blink         (vc_cons[currcons].vc_s_blink)
 194 #define s_reverse       (vc_cons[currcons].vc_s_reverse)
 195 #define ulcolor         (vc_cons[currcons].vc_ulcolor)
 196 #define halfcolor       (vc_cons[currcons].vc_halfcolor)
 197 #define tab_stop        (vc_cons[currcons].vc_tab_stop)
 198 #define vcmode          (vt_cons[currcons].vc_mode)
 199 #define vtmode          (vt_cons[currcons].vt_mode)
 200 #define vtpid           (vt_cons[currcons].vt_pid)
 201 #define vtnewvt         (vt_cons[currcons].vt_newvt)
 202 
 203 #define set_kbd(x) set_vc_kbd_mode(kbd_table+currcons,x)
 204 #define clr_kbd(x) clr_vc_kbd_mode(kbd_table+currcons,x)
 205 #define is_kbd(x) vc_kbd_mode(kbd_table+currcons,x)
 206 
 207 #define decarm          VC_REPEAT
 208 #define decckm          VC_CKMODE
 209 #define kbdapplic       VC_APPLIC
 210 #define kbdraw          VC_RAW
 211 #define lnm             VC_CRLF
 212 
 213 int blankinterval = 10*60*HZ;
 214 static int screen_size = 0;
 215 
 216 /*
 217  * this is what the terminal answers to a ESC-Z or csi0c query.
 218  */
 219 #define VT100ID "\033[?1;2c"
 220 #define VT102ID "\033[?6c"
 221 
 222 static unsigned char * translations[] = {
 223 /* 8-bit Latin-1 mapped to the PC character set: '\0' means non-printable */
 224 (unsigned char *)
 225         "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
 226         "\0\0\0\0\0\0\0\0\0\0\376\0\0\0\0\0"
 227         " !\"#$%&'()*+,-./0123456789:;<=>?"
 228         "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
 229         "`abcdefghijklmnopqrstuvwxyz{|}~\0"
 230         "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
 231         "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
 232         "\377\255\233\234\376\235\174\025\376\376\246\256\252\055\376\376"
 233         "\370\361\375\376\376\346\024\371\376\376\247\257\254\253\376\250"
 234         "\376\376\376\376\216\217\222\200\376\220\376\376\376\376\376\376"
 235         "\376\245\376\376\376\376\231\376\350\376\376\376\232\376\376\341"
 236         "\205\240\203\376\204\206\221\207\212\202\210\211\215\241\214\213"
 237         "\376\244\225\242\223\376\224\366\355\227\243\226\201\376\376\230",
 238 /* vt100 graphics */
 239 (unsigned char *)
 240         "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
 241         "\0\0\0\0\0\0\0\0\0\0\376\0\0\0\0\0"
 242         " !\"#$%&'()*+,-./0123456789:;<=>?"
 243         "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^ "
 244         "\004\261\007\007\007\007\370\361\007\007\331\277\332\300\305\304"
 245         "\304\304\137\137\303\264\301\302\263\363\362\343\330\234\007\0"
 246         "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
 247         "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
 248         "\377\255\233\234\376\235\174\025\376\376\246\256\252\055\376\376"
 249         "\370\361\375\376\376\346\024\371\376\376\247\257\254\253\376\250"
 250         "\376\376\376\376\216\217\222\200\376\220\376\376\376\376\376\376"
 251         "\376\245\376\376\376\376\231\376\376\376\376\376\232\376\376\341"
 252         "\205\240\203\376\204\206\221\207\212\202\210\211\215\241\214\213"
 253         "\376\244\225\242\223\376\224\366\376\227\243\226\201\376\376\230",
 254 /* IBM graphics: minimal translations (BS, CR, LF, LL, SO, SI and ESC) */
 255 (unsigned char *)
 256         "\000\001\002\003\004\005\006\007\000\011\000\013\000\000\000\000"
 257         "\020\021\022\023\024\025\026\027\030\031\032\000\034\035\036\037"
 258         "\040\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057"
 259         "\060\061\062\063\064\065\066\067\070\071\072\073\074\075\076\077"
 260         "\100\101\102\103\104\105\106\107\110\111\112\113\114\115\116\117"
 261         "\120\121\122\123\124\125\126\127\130\131\132\133\134\135\136\137"
 262         "\140\141\142\143\144\145\146\147\150\151\152\153\154\155\156\157"
 263         "\160\161\162\163\164\165\166\167\170\171\172\173\174\175\176\177"
 264         "\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217"
 265         "\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237"
 266         "\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257"
 267         "\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277"
 268         "\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317"
 269         "\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337"
 270         "\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357"
 271         "\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377",
 272  /* USER: customizable mappings, initialized as the previous one (IBM) */
 273 (unsigned char *)
 274         "\000\001\002\003\004\005\006\007\010\011\000\013\000\000\016\017"
 275         "\020\021\022\023\024\025\026\027\030\031\032\000\034\035\036\037"
 276         "\040\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057"
 277         "\060\061\062\063\064\065\066\067\070\071\072\073\074\075\076\077"
 278         "\100\101\102\103\104\105\106\107\110\111\112\113\114\115\116\117"
 279         "\120\121\122\123\124\125\126\127\130\131\132\133\134\135\136\137"
 280         "\140\141\142\143\144\145\146\147\150\151\152\153\154\155\156\157"
 281         "\160\161\162\163\164\165\166\167\170\171\172\173\174\175\176\177"
 282         "\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217"
 283         "\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237"
 284         "\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257"
 285         "\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277"
 286         "\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317"
 287         "\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337"
 288         "\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357"
 289         "\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377"
 290 };
 291 
 292 #define NORM_TRANS (translations[0])
 293 #define GRAF_TRANS (translations[1])
 294 #define NULL_TRANS (translations[2])
 295 #define USER_TRANS (translations[3])
 296 
 297 static unsigned char color_table[] = { 0, 4, 2, 6, 1, 5, 3, 7,
 298                                        8,12,10,14, 9,13,11,15 };
 299 
 300 /*
 301  * gotoxy() must verify all boundaries, because the arguments
 302  * might also be negative. If the given position is out of
 303  * bounds, the cursor is placed at the nearest margin.
 304  */
 305 static void gotoxy(int currcons, int new_x, int new_y)
     /* [previous][next][first][last][top][bottom][index][help] */
 306 {
 307         int max_y;
 308 
 309         if (new_x < 0)
 310                 x = 0;
 311         else
 312                 if (new_x >= video_num_columns)
 313                         x = video_num_columns - 1;
 314                 else
 315                         x = new_x;
 316         if (decom) {
 317                 new_y += top;
 318                 max_y = bottom;
 319         } else
 320                 max_y = video_num_lines;
 321         if (new_y < 0)
 322                 y = 0;
 323         else
 324                 if (new_y >= max_y)
 325                         y = max_y - 1;
 326                 else
 327                         y = new_y;
 328         pos = origin + y*video_size_row + (x<<1);
 329         need_wrap = 0;
 330 }
 331 
 332 /*
 333  * *Very* limited hardware scrollback support..
 334  */
 335 static unsigned short __real_origin;
 336 static unsigned short __origin;
 337 
 338 static inline void __set_origin(unsigned short offset)
     /* [previous][next][first][last][top][bottom][index][help] */
 339 {
 340         unsigned long flags;
 341 #ifdef CONFIG_SELECTION
 342         clear_selection();
 343 #endif /* CONFIG_SELECTION */
 344         save_flags(flags); cli();
 345         __origin = offset;
 346         outb_p(12, video_port_reg);
 347         outb_p(offset >> 8, video_port_val);
 348         outb_p(13, video_port_reg);
 349         outb_p(offset, video_port_val);
 350         restore_flags(flags);
 351 }
 352 
 353 void scrollback(int lines)
     /* [previous][next][first][last][top][bottom][index][help] */
 354 {
 355         if (!lines)
 356                 lines = video_num_lines/2;
 357         lines *= video_num_columns;
 358         lines = __origin - lines;
 359         if (lines < 0)
 360                 lines = 0;
 361         __set_origin(lines);
 362 }
 363 
 364 void scrollfront(int lines)
     /* [previous][next][first][last][top][bottom][index][help] */
 365 {
 366         if (!lines)
 367                 lines = video_num_lines/2;
 368         lines *= video_num_columns;
 369         lines = __origin + lines;
 370         if (lines > __real_origin)
 371                 lines = __real_origin;
 372         __set_origin(lines);
 373 }
 374 
 375 static void set_origin(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 376 {
 377         if (video_type != VIDEO_TYPE_EGAC && video_type != VIDEO_TYPE_EGAM)
 378                 return;
 379         if (currcons != fg_console || console_blanked || vcmode == KD_GRAPHICS)
 380                 return;
 381         __real_origin = (origin-video_mem_base) >> 1;
 382         __set_origin(__real_origin);
 383 }
 384 
 385 static inline void hide_cursor(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 386 {
 387         outb_p(14, video_port_reg);
 388         outb_p(0xff&((scr_end-video_mem_base)>>9), video_port_val);
 389         outb_p(15, video_port_reg);
 390         outb_p(0xff&((scr_end-video_mem_base)>>1), video_port_val);
 391 }
 392 
 393 static inline void set_cursor(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 394 {
 395         unsigned long flags;
 396 
 397         if (currcons != fg_console || console_blanked || vcmode == KD_GRAPHICS)
 398                 return;
 399         if (__real_origin != __origin)
 400                 set_origin(__real_origin);
 401         save_flags(flags); cli();
 402         if (deccm) {
 403                 outb_p(14, video_port_reg);
 404                 outb_p(0xff&((pos-video_mem_base)>>9), video_port_val);
 405                 outb_p(15, video_port_reg);
 406                 outb_p(0xff&((pos-video_mem_base)>>1), video_port_val);
 407         } else
 408                 hide_cursor(currcons);
 409         restore_flags(flags);
 410 }
 411 
 412 static void scrup(int currcons, unsigned int t, unsigned int b)
     /* [previous][next][first][last][top][bottom][index][help] */
 413 {
 414         int hardscroll = 1;
 415 
 416         if (b > video_num_lines || t >= b)
 417                 return;
 418         if (video_type != VIDEO_TYPE_EGAC && video_type != VIDEO_TYPE_EGAM)
 419                 hardscroll = 0;
 420         else if (t || b != video_num_lines)
 421                 hardscroll = 0;
 422         if (hardscroll) {
 423                 origin += video_size_row;
 424                 pos += video_size_row;
 425                 scr_end += video_size_row;
 426                 if (scr_end > video_mem_end) {
 427                         __asm__("cld\n\t"
 428                                 "rep\n\t"
 429                                 "movsl\n\t"
 430                                 "movl _video_num_columns,%1\n\t"
 431                                 "rep\n\t"
 432                                 "stosw"
 433                                 : /* no output */
 434                                 :"a" (video_erase_char),
 435                                 "c" ((video_num_lines-1)*video_num_columns>>1),
 436                                 "D" (video_mem_start),
 437                                 "S" (origin)
 438                                 :"cx","di","si");
 439                         scr_end -= origin-video_mem_start;
 440                         pos -= origin-video_mem_start;
 441                         origin = video_mem_start;
 442                 } else {
 443                         __asm__("cld\n\t"
 444                                 "rep\n\t"
 445                                 "stosw"
 446                                 : /* no output */
 447                                 :"a" (video_erase_char),
 448                                 "c" (video_num_columns),
 449                                 "D" (scr_end-video_size_row)
 450                                 :"cx","di");
 451                 }
 452                 set_origin(currcons);
 453         } else {
 454                 __asm__("cld\n\t"
 455                         "rep\n\t"
 456                         "movsl\n\t"
 457                         "movl _video_num_columns,%%ecx\n\t"
 458                         "rep\n\t"
 459                         "stosw"
 460                         : /* no output */
 461                         :"a" (video_erase_char),
 462                         "c" ((b-t-1)*video_num_columns>>1),
 463                         "D" (origin+video_size_row*t),
 464                         "S" (origin+video_size_row*(t+1))
 465                         :"cx","di","si");
 466         }
 467 }
 468 
 469 static void scrdown(int currcons, unsigned int t, unsigned int b)
     /* [previous][next][first][last][top][bottom][index][help] */
 470 {
 471         if (b > video_num_lines || t >= b)
 472                 return;
 473         __asm__("std\n\t"
 474                 "rep\n\t"
 475                 "movsl\n\t"
 476                 "addl $2,%%edi\n\t"     /* %edi has been decremented by 4 */
 477                 "movl _video_num_columns,%%ecx\n\t"
 478                 "rep\n\t"
 479                 "stosw\n\t"
 480                 "cld"
 481                 : /* no output */
 482                 :"a" (video_erase_char),
 483                 "c" ((b-t-1)*video_num_columns>>1),
 484                 "D" (origin+video_size_row*b-4),
 485                 "S" (origin+video_size_row*(b-1)-4)
 486                 :"ax","cx","di","si");
 487 }
 488 
 489 static void lf(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 490 {
 491         if (y+1<bottom) {
 492                 y++;
 493                 pos += video_size_row;
 494                 return;
 495         } else 
 496                 scrup(currcons,top,bottom);
 497         need_wrap = 0;
 498 }
 499 
 500 static void ri(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 501 {
 502         if (y>top) {
 503                 y--;
 504                 pos -= video_size_row;
 505                 return;
 506         } else
 507                 scrdown(currcons,top,bottom);
 508         need_wrap = 0;
 509 }
 510 
 511 static inline void cr(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 512 {
 513         pos -= x<<1;
 514         need_wrap = x = 0;
 515 }
 516 
 517 static inline void bs(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 518 {
 519         if (x) {
 520                 pos -= 2;
 521                 x--;
 522                 need_wrap = 0;
 523         }
 524 }
 525 
 526 static inline void del(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 527 {
 528 #if 0
 529         if (x) {
 530                 if (!need_wrap) {    /* this is not the right condition */
 531                         pos -= 2;
 532                         x--;
 533                 }
 534                 *(unsigned short *)pos = video_erase_char;
 535                 need_wrap = 0;
 536         }
 537 #endif
 538 }
 539 
 540 static void csi_J(int currcons, int vpar)
     /* [previous][next][first][last][top][bottom][index][help] */
 541 {
 542         unsigned long count;
 543         unsigned long start;
 544 
 545         switch (vpar) {
 546                 case 0: /* erase from cursor to end of display */
 547                         count = (scr_end-pos)>>1;
 548                         start = pos;
 549                         break;
 550                 case 1: /* erase from start to cursor */
 551                         count = ((pos-origin)>>1)+1;
 552                         start = origin;
 553                         break;
 554                 case 2: /* erase whole display */
 555                         count = video_num_columns * video_num_lines;
 556                         start = origin;
 557                         break;
 558                 default:
 559                         return;
 560         }
 561         __asm__("cld\n\t"
 562                 "rep\n\t"
 563                 "stosw\n\t"
 564                 : /* no output */
 565                 :"c" (count),
 566                 "D" (start),"a" (video_erase_char)
 567                 :"cx","di");
 568         need_wrap = 0;
 569 }
 570 
 571 static void csi_K(int currcons, int vpar)
     /* [previous][next][first][last][top][bottom][index][help] */
 572 {
 573         long count;
 574         long start;
 575 
 576         switch (vpar) {
 577                 case 0: /* erase from cursor to end of line */
 578                         count = video_num_columns-x;
 579                         start = pos;
 580                         break;
 581                 case 1: /* erase from start of line to cursor */
 582                         start = pos - (x<<1);
 583                         count = x+1;
 584                         break;
 585                 case 2: /* erase whole line */
 586                         start = pos - (x<<1);
 587                         count = video_num_columns;
 588                         break;
 589                 default:
 590                         return;
 591         }
 592         __asm__("cld\n\t"
 593                 "rep\n\t"
 594                 "stosw\n\t"
 595                 : /* no output */
 596                 :"c" (count),
 597                 "D" (start),"a" (video_erase_char)
 598                 :"cx","di");
 599         need_wrap = 0;
 600 }
 601 
 602 /*
 603  *  I hope this works. The monochrome part is untested.
 604  */
 605 static void update_attr(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 606 {
 607         attr = color;
 608         if (can_do_color) {
 609                 if (underline)
 610                         attr = (attr & 0xf0) | ulcolor;
 611                 else if (intensity == 0)
 612                         attr = (attr & 0xf0) | halfcolor;
 613         }
 614         if (reverse ^ decscnm)
 615                 attr = (attr & 0x88) | (((attr >> 4) | (attr << 4)) & 0x77);
 616         if (blink)
 617                 attr ^= 0x80;
 618         if (intensity == 2)
 619                 attr ^= 0x08;
 620         if (!can_do_color) {
 621                 if (underline)
 622                         attr = (attr & 0xf8) | 0x01;
 623                 else if (intensity == 0)
 624                         attr = (attr & 0xf0) | 0x08;
 625         }
 626         if (decscnm)
 627                 video_erase_char = (((color & 0x88) | (((color >> 4) | (color << 4)) & 0x77)) << 8) | ' ';
 628         else
 629                 video_erase_char = (color << 8) | ' ';
 630 }
 631 
 632 static void default_attr(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 633 {
 634         intensity = 1;
 635         underline = 0;
 636         reverse = 0;
 637         blink = 0;
 638         color = def_color;
 639 }
 640 
 641 static void csi_m(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 642 {
 643         int i;
 644 
 645         for (i=0;i<=npar;i++)
 646                 switch (par[i]) {
 647                         case 0: /* all attributes off */
 648                                 default_attr(currcons);
 649                                 break;
 650                         case 1:
 651                                 intensity = 2;
 652                                 break;
 653                         case 2:
 654                                 intensity = 0;
 655                                 break;
 656                         case 4:
 657                                 underline = 1;
 658                                 break;
 659                         case 5:
 660                                 blink = 1;
 661                                 break;
 662                         case 7:
 663                                 reverse = 1;
 664                                 break;
 665                         case 21:
 666                         case 22:
 667                                 intensity = 1;
 668                                 break;
 669                         case 24:
 670                                 underline = 0;
 671                                 break;
 672                         case 25:
 673                                 blink = 0;
 674                                 break;
 675                         case 27:
 676                                 reverse = 0;
 677                                 break;
 678                         case 39:
 679                                 color = (def_color & 0x0f) | background;
 680                                 break;
 681                         case 49:
 682                                 color = (def_color & 0xf0) | foreground;
 683                                 break;
 684                         default:
 685                                 if (par[i] >= 30 && par[i] <= 37)
 686                                         color = color_table[par[i]-30]
 687                                                 | background; 
 688                                 else if (par[i] >= 40 && par[i] <= 47)
 689                                         color = (color_table[par[i]-40]<<4)
 690                                                 | foreground;
 691                                 break;
 692                 }
 693         update_attr(currcons);
 694 }
 695 
 696 static void respond_string(char * p, int currcons, struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 697 {
 698         while (*p) {
 699                 put_tty_queue(*p, &tty->read_q);
 700                 p++;
 701         }
 702         TTY_READ_FLUSH(tty);
 703 }
 704 
 705 static void respond_num(unsigned int n, int currcons, struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 706 {
 707         char buff[3];
 708         int i = 0;
 709 
 710         do {
 711                 buff[i++] = (n%10)+'0';
 712                 n /= 10;
 713         } while(n && i < 3);    /* We'll take no chances */
 714         while (i--) {
 715                 put_tty_queue(buff[i], &tty->read_q);
 716         }
 717         /* caller must flush */
 718 }
 719 
 720 static void cursor_report(int currcons, struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 721 {
 722         put_tty_queue('\033', &tty->read_q);
 723         put_tty_queue('[', &tty->read_q);
 724         respond_num(y + (decom ? top+1 : 1), currcons, tty);
 725         put_tty_queue(';', &tty->read_q);
 726         respond_num(x+1, currcons, tty);
 727         put_tty_queue('R', &tty->read_q);
 728         TTY_READ_FLUSH(tty);
 729 }
 730 
 731 static inline void status_report(int currcons, struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 732 {
 733         respond_string("\033[0n", currcons, tty);       /* Terminal ok */
 734 }
 735 
 736 static inline void respond_ID(int currcons, struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 737 {
 738         respond_string(VT102ID, currcons, tty);
 739 }
 740 
 741 static void invert_screen(int currcons) {
     /* [previous][next][first][last][top][bottom][index][help] */
 742         unsigned char *p;
 743 
 744         if (can_do_color)
 745                 for (p = (unsigned char *)origin+1; p < (unsigned char *)scr_end; p+=2)
 746                         *p = (*p & 0x88) | (((*p >> 4) | (*p << 4)) & 0x77);
 747         else
 748                 for (p = (unsigned char *)origin+1; p < (unsigned char *)scr_end; p+=2)
 749                         *p ^= *p & 0x07 == 1 ? 0x70 : 0x77;
 750 }
 751 
 752 static void set_mode(int currcons, int on_off)
     /* [previous][next][first][last][top][bottom][index][help] */
 753 {
 754         int i;
 755 
 756         for (i=0; i<=npar; i++)
 757                 if (ques) switch(par[i]) {      /* DEC private modes set/reset */
 758                         case 1:                 /* Cursor keys send ^[Ox/^[[x */
 759                                 if (on_off)
 760                                         set_kbd(decckm);
 761                                 else
 762                                         clr_kbd(decckm);
 763                                 break;
 764                         case 3: /* 80/132 mode switch unimplemented */
 765                                 csi_J(currcons,2);
 766                                 gotoxy(currcons,0,0);
 767                                 break;
 768                         case 5:                 /* Inverted screen on/off */
 769                                 if (decscnm != on_off) {
 770                                         decscnm = on_off;
 771                                         invert_screen(currcons);
 772                                         update_attr(currcons);
 773                                 }
 774                                 break;
 775                         case 6:                 /* Origin relative/absolute */
 776                                 decom = on_off;
 777                                 gotoxy(currcons,0,0);
 778                                 break;
 779                         case 7:                 /* Autowrap on/off */
 780                                 decawm = on_off;
 781                                 break;
 782                         case 8:                 /* Autorepeat on/off */
 783                                 if (on_off)
 784                                         set_kbd(decarm);
 785                                 else
 786                                         clr_kbd(decarm);
 787                                 break;
 788                         case 25:                /* Cursor on/off */
 789                                 deccm = on_off;
 790                                 set_cursor(currcons);
 791                                 break;
 792                 } else switch(par[i]) {         /* ANSI modes set/reset */
 793                         case 4:                 /* Insert Mode on/off */
 794                                 decim = on_off;
 795                                 break;
 796                         case 20:                /* Lf, Enter == CrLf/Lf */
 797                                 if (on_off)
 798                                         set_kbd(lnm);
 799                                 else
 800                                         clr_kbd(lnm);
 801                                 break;
 802                 }
 803 }
 804 
 805 static void setterm_command(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 806 {
 807         switch(par[0]) {
 808                 case 1: /* set color for underline mode */
 809                         if (can_do_color && par[1] < 16) {
 810                                 ulcolor = color_table[par[1]];
 811                                 if (underline)
 812                                         update_attr(currcons);
 813                         }
 814                         break;
 815                 case 2: /* set color for half intensity mode */
 816                         if (can_do_color && par[1] < 16) {
 817                                 halfcolor = color_table[par[1]];
 818                                 if (intensity == 0)
 819                                         update_attr(currcons);
 820                         }
 821                         break;
 822                 case 8: /* store colors as defaults */
 823                         def_color = attr;
 824                         default_attr(currcons);
 825                         update_attr(currcons);
 826                         break;
 827                 case 9: /* set blanking interval */
 828                         blankinterval = ((par[1] < 60) ? par[1] : 60) * 60 * HZ;
 829                         break;
 830         }
 831 }
 832 
 833 static void insert_char(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 834 {
 835         unsigned int i = x;
 836         unsigned short tmp, old = video_erase_char;
 837         unsigned short * p = (unsigned short *) pos;
 838 
 839         while (i++ < video_num_columns) {
 840                 tmp = *p;
 841                 *p = old;
 842                 old = tmp;
 843                 p++;
 844         }
 845         need_wrap = 0;
 846 }
 847 
 848 static void insert_line(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 849 {
 850         scrdown(currcons,y,bottom);
 851         need_wrap = 0;
 852 }
 853 
 854 static void delete_char(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 855 {
 856         unsigned int i = x;
 857         unsigned short * p = (unsigned short *) pos;
 858 
 859         while (++i < video_num_columns) {
 860                 *p = *(p+1);
 861                 p++;
 862         }
 863         *p = video_erase_char;
 864         need_wrap = 0;
 865 }
 866 
 867 static void delete_line(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 868 {
 869         scrup(currcons,y,bottom);
 870         need_wrap = 0;
 871 }
 872 
 873 static void csi_at(int currcons, unsigned int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
 874 {
 875         if (nr > video_num_columns)
 876                 nr = video_num_columns;
 877         else if (!nr)
 878                 nr = 1;
 879         while (nr--)
 880                 insert_char(currcons);
 881 }
 882 
 883 static void csi_L(int currcons, unsigned int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
 884 {
 885         if (nr > video_num_lines)
 886                 nr = video_num_lines;
 887         else if (!nr)
 888                 nr = 1;
 889         while (nr--)
 890                 insert_line(currcons);
 891 }
 892 
 893 static void csi_P(int currcons, unsigned int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
 894 {
 895         if (nr > video_num_columns)
 896                 nr = video_num_columns;
 897         else if (!nr)
 898                 nr = 1;
 899         while (nr--)
 900                 delete_char(currcons);
 901 }
 902 
 903 static void csi_M(int currcons, unsigned int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
 904 {
 905         if (nr > video_num_lines)
 906                 nr = video_num_lines;
 907         else if (!nr)
 908                 nr=1;
 909         while (nr--)
 910                 delete_line(currcons);
 911 }
 912 
 913 static void save_cur(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 914 {
 915         saved_x         = x;
 916         saved_y         = y;
 917         s_intensity     = intensity;
 918         s_underline     = underline;
 919         s_blink         = blink;
 920         s_reverse       = reverse;
 921         s_charset       = charset;
 922         s_color         = color;
 923         saved_G0        = G0_charset;
 924         saved_G1        = G1_charset;
 925 }
 926 
 927 static void restore_cur(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 928 {
 929         gotoxy(currcons,saved_x,saved_y);
 930         intensity       = s_intensity;
 931         underline       = s_underline;
 932         blink           = s_blink;
 933         reverse         = s_reverse;
 934         charset         = s_charset;
 935         color           = s_color;
 936         G0_charset      = saved_G0;
 937         G1_charset      = saved_G1;
 938         translate       = charset ? G1_charset : G0_charset;
 939         update_attr(currcons);
 940         need_wrap = 0;
 941 }
 942 
 943 enum { ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey, 
 944         EShash, ESsetG0, ESsetG1, ESignore };
 945 
 946 static void reset_terminal(int currcons, int do_clear)
     /* [previous][next][first][last][top][bottom][index][help] */
 947 {
 948         top             = 0;
 949         bottom          = video_num_lines;
 950         state           = ESnormal;
 951         ques            = 0;
 952         translate       = NORM_TRANS;
 953         G0_charset      = NORM_TRANS;
 954         G1_charset      = GRAF_TRANS;
 955         charset         = 0;
 956         need_wrap       = 0;
 957 
 958         decscnm         = 0;
 959         decom           = 0;
 960         decawm          = 1;
 961         deccm           = 1;
 962         decim           = 0;
 963 
 964         set_kbd(decarm);
 965         clr_kbd(decckm);
 966         clr_kbd(kbdapplic);
 967         clr_kbd(lnm);
 968         kbd_table[currcons].lockstate = 0;
 969         kbd_table[currcons].ledstate = kbd_table[currcons].default_ledstate;
 970         set_leds();
 971 
 972         default_attr(currcons);
 973         update_attr(currcons);
 974 
 975         tab_stop[0]     = 0x01010100;
 976         tab_stop[1]     =
 977         tab_stop[2]     =
 978         tab_stop[3]     =
 979         tab_stop[4]     = 0x01010101;
 980 
 981         if (do_clear) {
 982                 gotoxy(currcons,0,0);
 983                 csi_J(currcons,2);
 984                 save_cur(currcons);
 985         }
 986 }
 987 
 988 void con_write(struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 989 {
 990         int c;
 991         unsigned int currcons;
 992 
 993         currcons = tty->line - 1;
 994         if (currcons >= NR_CONSOLES) {
 995                 printk("con_write: illegal tty (%d)\n", currcons);
 996                 return;
 997         }
 998 #ifdef CONFIG_SELECTION
 999         /* clear the selection as soon as any characters are to be written
1000            out on the console holding the selection. */
1001         if (!EMPTY(&tty->write_q) && currcons == sel_cons)
1002                 clear_selection();
1003 #endif /* CONFIG_SELECTION */
1004         disable_bh(KEYBOARD_BH);
1005         while (!tty->stopped && (c = get_tty_queue(&tty->write_q)) >= 0) {
1006                 if (state == ESnormal && translate[c]) {
1007                         if (need_wrap) {
1008                                 cr(currcons);
1009                                 lf(currcons);
1010                         }
1011                         if (decim)
1012                                 insert_char(currcons);
1013                         c = translate[c];
1014                         *(unsigned short *) pos = (attr << 8) + c;
1015                         if (x == video_num_columns - 1)
1016                                 need_wrap = decawm;
1017                         else {
1018                                 x++;
1019                                 pos+=2;
1020                         }
1021                         continue;
1022                 }
1023 
1024                 /*
1025                  *  Control characters can be used in the _middle_
1026                  *  of an escape sequence.
1027                  */
1028                 switch (c) {
1029                         case 7:
1030                                 kd_mksound(0x637, HZ/8);
1031                                 continue;
1032                         case 8:
1033                                 bs(currcons);
1034                                 continue;
1035                         case 9:
1036                                 pos -= (x << 1);
1037                                 while (x < video_num_columns - 1) {
1038                                         x++;
1039                                         if (tab_stop[x >> 5] & (1 << (x & 31)))
1040                                                 break;
1041                                 }
1042                                 pos += (x << 1);
1043                                 continue;
1044                         case 10: case 11: case 12:
1045                                 lf(currcons);
1046                                 if (!is_kbd(lnm))
1047                                         continue;
1048                         case 13:
1049                                 cr(currcons);
1050                                 continue;
1051                         case 14:
1052                                 charset = 1;
1053                                 translate = G1_charset;
1054                                 continue;
1055                         case 15:
1056                                 charset = 0;
1057                                 translate = G0_charset;
1058                                 continue;
1059                         case 24: case 26:
1060                                 state = ESnormal;
1061                                 continue;
1062                         case 27:
1063                                 state = ESesc;
1064                                 continue;
1065                         case 127:
1066                                 del(currcons);
1067                                 continue;
1068                         case 128+27:
1069                                 state = ESsquare;
1070                                 continue;
1071                 }
1072                 switch(state) {
1073                         case ESesc:
1074                                 state = ESnormal;
1075                                 switch (c) {
1076                                   case '[':
1077                                         state = ESsquare;
1078                                         continue;
1079                                   case 'E':
1080                                         cr(currcons);
1081                                         lf(currcons);
1082                                         continue;
1083                                   case 'M':
1084                                         ri(currcons);
1085                                         continue;
1086                                   case 'D':
1087                                         lf(currcons);
1088                                         continue;
1089                                   case 'H':
1090                                         tab_stop[x >> 5] |= (1 << (x & 31));
1091                                         continue;
1092                                   case 'Z':
1093                                         respond_ID(currcons,tty);
1094                                         continue;
1095                                   case '7':
1096                                         save_cur(currcons);
1097                                         continue;
1098                                   case '8':
1099                                         restore_cur(currcons);
1100                                         continue;
1101                                   case '(':
1102                                         state = ESsetG0;
1103                                         continue;
1104                                   case ')':
1105                                         state = ESsetG1;
1106                                         continue;
1107                                   case '#':
1108                                         state = EShash;
1109                                         continue;
1110                                   case 'c':
1111                                         reset_terminal(currcons,1);
1112                                         continue;
1113                                   case '>':  /* Numeric keypad */
1114                                         clr_kbd(kbdapplic);
1115                                         continue;
1116                                   case '=':  /* Appl. keypad */
1117                                         set_kbd(kbdapplic);
1118                                         continue;
1119                                 }       
1120                                 continue;
1121                         case ESsquare:
1122                                 for(npar = 0 ; npar < NPAR ; npar++)
1123                                         par[npar] = 0;
1124                                 npar = 0;
1125                                 state = ESgetpars;
1126                                 if (c == '[') { /* Function key */
1127                                         state=ESfunckey;
1128                                         continue;
1129                                 }
1130                                 ques = (c=='?');
1131                                 if (ques)
1132                                         continue;
1133                         case ESgetpars:
1134                                 if (c==';' && npar<NPAR-1) {
1135                                         npar++;
1136                                         continue;
1137                                 } else if (c>='0' && c<='9') {
1138                                         par[npar] *= 10;
1139                                         par[npar] += c-'0';
1140                                         continue;
1141                                 } else state=ESgotpars;
1142                         case ESgotpars:
1143                                 state = ESnormal;
1144                                 switch(c) {
1145                                         case 'h':
1146                                                 set_mode(currcons,1);
1147                                                 continue;
1148                                         case 'l':
1149                                                 set_mode(currcons,0);
1150                                                 continue;
1151                                         case 'n':
1152                                                 if (!ques)
1153                                                         if (par[0] == 5)
1154                                                                 status_report(currcons,tty);
1155                                                         else if (par[0] == 6)
1156                                                                 cursor_report(currcons,tty);
1157                                                 continue;
1158                                 }
1159                                 if (ques) {
1160                                         ques = 0;
1161                                         continue;
1162                                 }
1163                                 switch(c) {
1164                                         case 'G': case '`':
1165                                                 if (par[0]) par[0]--;
1166                                                 gotoxy(currcons,par[0],y);
1167                                                 continue;
1168                                         case 'A':
1169                                                 if (!par[0]) par[0]++;
1170                                                 gotoxy(currcons,x,y-par[0]);
1171                                                 continue;
1172                                         case 'B': case 'e':
1173                                                 if (!par[0]) par[0]++;
1174                                                 gotoxy(currcons,x,y+par[0]);
1175                                                 continue;
1176                                         case 'C': case 'a':
1177                                                 if (!par[0]) par[0]++;
1178                                                 gotoxy(currcons,x+par[0],y);
1179                                                 continue;
1180                                         case 'D':
1181                                                 if (!par[0]) par[0]++;
1182                                                 gotoxy(currcons,x-par[0],y);
1183                                                 continue;
1184                                         case 'E':
1185                                                 if (!par[0]) par[0]++;
1186                                                 gotoxy(currcons,0,y+par[0]);
1187                                                 continue;
1188                                         case 'F':
1189                                                 if (!par[0]) par[0]++;
1190                                                 gotoxy(currcons,0,y-par[0]);
1191                                                 continue;
1192                                         case 'd':
1193                                                 if (par[0]) par[0]--;
1194                                                 gotoxy(currcons,x,par[0]);
1195                                                 continue;
1196                                         case 'H': case 'f':
1197                                                 if (par[0]) par[0]--;
1198                                                 if (par[1]) par[1]--;
1199                                                 gotoxy(currcons,par[1],par[0]);
1200                                                 continue;
1201                                         case 'J':
1202                                                 csi_J(currcons,par[0]);
1203                                                 continue;
1204                                         case 'K':
1205                                                 csi_K(currcons,par[0]);
1206                                                 continue;
1207                                         case 'L':
1208                                                 csi_L(currcons,par[0]);
1209                                                 continue;
1210                                         case 'M':
1211                                                 csi_M(currcons,par[0]);
1212                                                 continue;
1213                                         case 'P':
1214                                                 csi_P(currcons,par[0]);
1215                                                 continue;
1216                                         case 'c':
1217                                                 if (!par[0])
1218                                                         respond_ID(currcons,tty);
1219                                                 continue;
1220                                         case 'g':
1221                                                 if (!par[0])
1222                                                         tab_stop[x >> 5] &= ~(1 << (x & 31));
1223                                                 else if (par[0] == 3) {
1224                                                         tab_stop[0] =
1225                                                         tab_stop[1] =
1226                                                         tab_stop[2] =
1227                                                         tab_stop[3] =
1228                                                         tab_stop[4] = 0;
1229                                                 }
1230                                                 continue;
1231                                         case 'm':
1232                                                 csi_m(currcons);
1233                                                 continue;
1234                                         case 'r':
1235                                                 if (!par[0])
1236                                                         par[0]++;
1237                                                 if (!par[1])
1238                                                         par[1] = video_num_lines;
1239                                                 /* Minimum allowed region is 2 lines */
1240                                                 if (par[0] < par[1] &&
1241                                                     par[1] <= video_num_lines) {
1242                                                         top=par[0]-1;
1243                                                         bottom=par[1];
1244                                                         gotoxy(currcons,0,0);
1245                                                 }
1246                                                 continue;
1247                                         case 's':
1248                                                 save_cur(currcons);
1249                                                 continue;
1250                                         case 'u':
1251                                                 restore_cur(currcons);
1252                                                 continue;
1253                                         case '@':
1254                                                 csi_at(currcons,par[0]);
1255                                                 continue;
1256                                         case ']': /* setterm functions */
1257                                                 setterm_command(currcons);
1258                                                 continue;
1259                                 }
1260                                 continue;
1261                         case ESfunckey:
1262                                 state = ESnormal;
1263                                 continue;
1264                         case EShash:
1265                                 state = ESnormal;
1266                                 if (c == '8') {
1267                                         /* DEC screen alignment test. kludge :-) */
1268                                         video_erase_char =
1269                                                 (video_erase_char & 0xff00) | 'E';
1270                                         csi_J(currcons, 2);
1271                                         video_erase_char =
1272                                                 (video_erase_char & 0xff00) | ' ';
1273                                 }
1274                                 continue;
1275                         case ESsetG0:
1276                                 if (c == '0')
1277                                         G0_charset = GRAF_TRANS;
1278                                 else if (c == 'B')
1279                                         G0_charset = NORM_TRANS;
1280                                 else if (c == 'U')
1281                                         G0_charset = NULL_TRANS;
1282                                 else if (c == 'K')
1283                                         G0_charset = USER_TRANS;
1284                                 if (charset == 0)
1285                                         translate = G0_charset;
1286                                 state = ESnormal;
1287                                 continue;
1288                         case ESsetG1:
1289                                 if (c == '0')
1290                                         G1_charset = GRAF_TRANS;
1291                                 else if (c == 'B')
1292                                         G1_charset = NORM_TRANS;
1293                                 else if (c == 'U')
1294                                         G1_charset = NULL_TRANS;
1295                                 else if (c == 'K')
1296                                         G1_charset = USER_TRANS;
1297                                 if (charset == 1)
1298                                         translate = G1_charset;
1299                                 state = ESnormal;
1300                                 continue;
1301                         default:
1302                                 state = ESnormal;
1303                 }
1304         }
1305         if (vcmode != KD_GRAPHICS)
1306                 set_cursor(currcons);
1307         enable_bh(KEYBOARD_BH);
1308         if (LEFT(&tty->write_q) > WAKEUP_CHARS)
1309                 wake_up_interruptible(&tty->write_q.proc_list);
1310 }
1311 
1312 void do_keyboard_interrupt(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1313 {
1314         TTY_READ_FLUSH(TTY_TABLE(0));
1315         timer_active &= ~(1<<BLANK_TIMER);
1316         if (vt_cons[fg_console].vc_mode == KD_GRAPHICS)
1317                 return;
1318         if (console_blanked) {
1319                 timer_table[BLANK_TIMER].expires = 0;
1320                 timer_active |= 1<<BLANK_TIMER;
1321         } else if (blankinterval) {
1322                 timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
1323                 timer_active |= 1<<BLANK_TIMER;
1324         }
1325 }
1326 
1327 void * memsetw(void * s,unsigned short c,int count)
     /* [previous][next][first][last][top][bottom][index][help] */
1328 {
1329 __asm__("cld\n\t"
1330         "rep\n\t"
1331         "stosw"
1332         : /* no output */
1333         :"a" (c),"D" (s),"c" (count)
1334         :"cx","di");
1335 return s;
1336 }
1337 
1338 void console_print(const char * b)
     /* [previous][next][first][last][top][bottom][index][help] */
1339 {
1340         int currcons = fg_console;
1341         unsigned char c;
1342 
1343         if (!printable || currcons<0 || currcons>=NR_CONSOLES)
1344                 return;
1345         while ((c = *(b++)) != 0) {
1346                 if (c == 10 || c == 13 || need_wrap) {
1347                         if (c != 13)
1348                                 lf(currcons);
1349                         cr(currcons);
1350                         if (c == 10 || c == 13)
1351                                 continue;
1352                 }
1353                 *(unsigned short *) pos = (attr << 8) + c;
1354                 if (x == video_num_columns - 1) {
1355                         need_wrap = 1;
1356                         continue;
1357                 }
1358                 x++;
1359                 pos+=2;
1360         }
1361         set_cursor(currcons);
1362         if (vt_cons[fg_console].vc_mode == KD_GRAPHICS)
1363                 return;
1364         timer_active &= ~(1<<BLANK_TIMER);
1365         if (console_blanked) {
1366                 timer_table[BLANK_TIMER].expires = 0;
1367                 timer_active |= 1<<BLANK_TIMER;
1368         } else if (blankinterval) {
1369                 timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
1370                 timer_active |= 1<<BLANK_TIMER;
1371         }
1372 }
1373 
1374 /*
1375  *  long con_init(long);
1376  *
1377  * This routine initalizes console interrupts, and does nothing
1378  * else. If you want the screen to clear, call tty_write with
1379  * the appropriate escape-sequece.
1380  *
1381  * Reads the information preserved by setup.s to determine the current display
1382  * type and sets everything accordingly.
1383  */
1384 long con_init(long kmem_start)
     /* [previous][next][first][last][top][bottom][index][help] */
1385 {
1386         char *display_desc = "????";
1387         int currcons = 0;
1388         long base;
1389         int orig_x = ORIG_X;
1390         int orig_y = ORIG_Y;
1391 
1392         vc_scrmembuf = (unsigned short *) kmem_start;
1393         video_num_columns = ORIG_VIDEO_COLS;
1394         video_size_row = video_num_columns * 2;
1395         video_num_lines = ORIG_VIDEO_LINES;
1396         video_page = ORIG_VIDEO_PAGE;
1397         screen_size = (video_num_lines * video_size_row);
1398         kmem_start += NR_CONSOLES * screen_size;
1399         timer_table[BLANK_TIMER].fn = blank_screen;
1400         timer_table[BLANK_TIMER].expires = 0;
1401         if (blankinterval) {
1402                 timer_table[BLANK_TIMER].expires = jiffies+blankinterval;
1403                 timer_active |= 1<<BLANK_TIMER;
1404         }
1405         
1406         if (ORIG_VIDEO_MODE == 7)       /* Is this a monochrome display? */
1407         {
1408                 video_mem_base = 0xb0000;
1409                 video_port_reg = 0x3b4;
1410                 video_port_val = 0x3b5;
1411                 if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
1412                 {
1413                         video_type = VIDEO_TYPE_EGAM;
1414                         video_mem_term = 0xb8000;
1415                         display_desc = "EGA+";
1416                 }
1417                 else
1418                 {
1419                         video_type = VIDEO_TYPE_MDA;
1420                         video_mem_term = 0xb2000;
1421                         display_desc = "*MDA";
1422                 }
1423         }
1424         else                            /* If not, it is color. */
1425         {
1426                 can_do_color = 1;
1427                 video_mem_base = 0xb8000;
1428                 video_port_reg  = 0x3d4;
1429                 video_port_val  = 0x3d5;
1430                 if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
1431                 {
1432                         video_type = VIDEO_TYPE_EGAC;
1433                         video_mem_term = 0xc0000;
1434                         display_desc = "EGA+";
1435                 }
1436                 else
1437                 {
1438                         video_type = VIDEO_TYPE_CGA;
1439                         video_mem_term = 0xba000;
1440                         display_desc = "*CGA";
1441                 }
1442         }
1443         
1444         /* Initialize the variables used for scrolling (mostly EGA/VGA) */
1445 
1446         base = (long)vc_scrmembuf;
1447         for (currcons = 0; currcons<NR_CONSOLES; currcons++) {
1448                 pos = origin = video_mem_start = base;
1449                 scr_end = video_mem_end = (base += screen_size);
1450                 vc_scrbuf[currcons] = (unsigned short *) origin;
1451                 vcmode          = KD_TEXT;
1452                 vtmode.mode     = VT_AUTO;
1453                 vtmode.waitv    = 0;
1454                 vtmode.relsig   = 0;
1455                 vtmode.acqsig   = 0;
1456                 vtmode.frsig    = 0;
1457                 vtpid           = -1;
1458                 vtnewvt         = -1;
1459                 clr_kbd(kbdraw);
1460                 def_color       = 0x07;   /* white */
1461                 ulcolor         = 0x0f;   /* bold white */
1462                 halfcolor       = 0x08;   /* grey */
1463                 reset_terminal(currcons, currcons);
1464         }
1465         currcons = fg_console = 0;
1466 
1467         video_mem_start = video_mem_base;
1468         video_mem_end = video_mem_term;
1469         origin = video_mem_start;
1470         scr_end = video_mem_start + video_num_lines * video_size_row;
1471         gotoxy(currcons,0,0);
1472         save_cur(currcons);
1473         gotoxy(currcons,orig_x,orig_y);
1474         update_screen(fg_console);
1475         printable = 1;
1476         printk("Console: %s %s %ldx%ld, %d virtual consoles\n",
1477                 can_do_color?"colour":"mono",
1478                 display_desc,
1479                 video_num_columns,video_num_lines,
1480                 NR_CONSOLES);
1481         register_console(console_print);
1482         return kmem_start;
1483 }
1484 
1485 /*
1486  * kbdsave doesn't need to do anything: it's all handled automatically
1487  * with the new data structures..
1488  */
1489 void kbdsave(int new_console)
     /* [previous][next][first][last][top][bottom][index][help] */
1490 {
1491 }
1492 
1493 static void get_scrmem(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
1494 {
1495         memcpy((void *)vc_scrbuf[currcons],(void *)origin, screen_size);
1496         video_mem_start = (unsigned long)vc_scrbuf[currcons];
1497         origin  = video_mem_start;
1498         scr_end = video_mem_end = video_mem_start+screen_size;
1499         pos = origin + y*video_size_row + (x<<1);
1500 }
1501 
1502 static void set_scrmem(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
1503 {
1504 #ifdef CONFIG_HGA
1505   /* This works with XFree86 1.2, 1.3 and 2.0
1506      This code could be extended and made more generally useful if we could
1507      determine the actual video mode. It appears that this should be
1508      possible on a genuine Hercules card, but I (WM) haven't been able to
1509      read from any of the required registers on my clone card.
1510      */
1511         /* This code should work with Hercules and MDA cards. */
1512         if (video_type == VIDEO_TYPE_MDA)
1513           {
1514             if (vcmode == KD_TEXT)
1515               {
1516                 /* Ensure that the card is in text mode. */
1517                 int     i;
1518                 static char herc_txt_tbl[12] = {
1519                   0x61,0x50,0x52,0x0f,0x19,6,0x19,0x19,2,0x0d,0x0b,0x0c };
1520                 outb_p(0, 0x3bf);  /* Back to power-on defaults */
1521                 outb_p(0, 0x3b8);  /* Blank the screen, select page 0, etc */
1522                 for ( i = 0 ; i < 12 ; i++ )
1523                   {
1524                     outb_p(i, 0x3b4);
1525                     outb_p(herc_txt_tbl[i], 0x3b5);
1526                   }
1527               }
1528 #define HGA_BLINKER_ON 0x20
1529 #define HGA_SCREEN_ON  8
1530             /* Make sure that the hardware is not blanked */
1531             outb_p(HGA_BLINKER_ON | HGA_SCREEN_ON, 0x3b8);
1532           }
1533 #endif CONFIG_HGA
1534 
1535         video_mem_start = video_mem_base;
1536         video_mem_end = video_mem_term;
1537         origin  = video_mem_start;
1538         scr_end = video_mem_start + screen_size;
1539         pos = origin + y*video_size_row + (x<<1);
1540         memcpy((void *)video_mem_base, (void *)vc_scrbuf[fg_console], screen_size);
1541 }
1542 
1543 void blank_screen(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1544 {
1545         if (console_blanked)
1546                 return;
1547         timer_table[BLANK_TIMER].fn = unblank_screen;
1548         get_scrmem(fg_console);
1549         hide_cursor(fg_console);
1550         console_blanked = 1;
1551         memsetw((void *)video_mem_base, 0x0020, video_mem_term-video_mem_base );
1552 }
1553 
1554 void unblank_screen(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1555 {
1556         if (!console_blanked)
1557                 return;
1558         timer_table[BLANK_TIMER].fn = blank_screen;
1559         if (blankinterval) {
1560                 timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
1561                 timer_active |= 1<<BLANK_TIMER;
1562         }
1563         console_blanked = 0;
1564         set_scrmem(fg_console);
1565         set_origin(fg_console);
1566         set_cursor(fg_console);
1567 }
1568 
1569 void update_screen(int new_console)
     /* [previous][next][first][last][top][bottom][index][help] */
1570 {
1571         static int lock = 0;
1572 
1573         if (new_console == fg_console || lock)
1574                 return;
1575         lock = 1;
1576         kbdsave(new_console);
1577         get_scrmem(fg_console); 
1578         fg_console = new_console;
1579         set_scrmem(fg_console); 
1580         set_origin(fg_console);
1581         set_cursor(new_console);
1582         set_leds();
1583         compute_shiftstate();
1584         lock = 0;
1585 }
1586 
1587 int do_screendump(int arg)
     /* [previous][next][first][last][top][bottom][index][help] */
1588 {
1589         char *sptr, *buf = (char *)arg;
1590         int currcons, l;
1591 
1592         if (!suser())
1593                 return -EPERM;
1594         l = verify_area(VERIFY_WRITE, buf,2+video_num_columns*video_num_lines);
1595         if (l)
1596                 return l;
1597         currcons = get_fs_byte(buf+1);
1598         if ((currcons<0) || (currcons>NR_CONSOLES))
1599                 return -EIO;
1600         put_fs_byte((char)(video_num_lines),buf++);     
1601         put_fs_byte((char)(video_num_columns),buf++);
1602         currcons = (currcons ? currcons-1 : fg_console);
1603         sptr = (char *) origin;
1604         for (l=video_num_lines*video_num_columns; l>0 ; l--, sptr++)
1605                 put_fs_byte(*sptr++,buf++);     
1606         return(0);
1607 }
1608 
1609 /*
1610  * All we do is set the write and ioctl subroutines; later on maybe we'll
1611  * dynamically allocate the console screen memory.
1612  */
1613 int con_open(struct tty_struct *tty, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
1614 {
1615         tty->write = con_write;
1616         tty->ioctl = vt_ioctl;
1617         if (tty->line > NR_CONSOLES)
1618                 return -ENODEV;
1619         return 0;
1620 }
1621 
1622 #ifdef CONFIG_SELECTION
1623 /* correction factor for when screen is hardware-scrolled */
1624 #define hwscroll_offset (currcons == fg_console ? ((__real_origin - __origin) << 1) : 0)
1625 
1626 /* set reverse video on characters s-e of console with selection. */
1627 static void highlight(const int currcons, const int s, const int e)
     /* [previous][next][first][last][top][bottom][index][help] */
1628 {
1629         unsigned char *p, *p1, *p2;
1630 
1631         p1 = (unsigned char *)origin - hwscroll_offset + s + 1;
1632         p2 = (unsigned char *)origin - hwscroll_offset + e + 1;
1633         if (p1 > p2)
1634         {
1635                 p = p1;
1636                 p1 = p2;
1637                 p2 = p;
1638         }
1639         for (p = p1; p <= p2; p += 2)
1640                 *p = (*p & 0x88) | ((*p << 4) & 0x70) | ((*p >> 4) & 0x07);
1641 }
1642 
1643 /* is c in range [a-zA-Z0-9_]? */
1644 static inline int inword(const char c) { return (isalnum(c) || c == '_'); }
     /* [previous][next][first][last][top][bottom][index][help] */
1645 
1646 /* does screen address p correspond to character at LH/RH edge of screen? */
1647 static inline int atedge(const int p)
     /* [previous][next][first][last][top][bottom][index][help] */
1648 {
1649         return (!(p % video_size_row) || !((p + 2) % video_size_row));
1650 }
1651 
1652 /* constrain v such that l <= v <= u */
1653 static inline short limit(const int v, const int l, const int u)
     /* [previous][next][first][last][top][bottom][index][help] */
1654 {
1655         return (v < l) ? l : ((v > u) ? u : v);
1656 }
1657 
1658 /* set the current selection. Invoked by ioctl(). */
1659 int set_selection(const int arg)
     /* [previous][next][first][last][top][bottom][index][help] */
1660 {
1661         unsigned short *args, xs, ys, xe, ye;
1662         int currcons = fg_console;
1663         int sel_mode, new_sel_start, new_sel_end, spc;
1664         char *bp, *obp, *spos;
1665         int i, ps, pe;
1666         char *off = (char *)origin - hwscroll_offset;
1667 
1668         unblank_screen();
1669         args = (unsigned short *)(arg + 1);
1670         xs = get_fs_word(args++) - 1;
1671         ys = get_fs_word(args++) - 1;
1672         xe = get_fs_word(args++) - 1;
1673         ye = get_fs_word(args++) - 1;
1674         sel_mode = get_fs_word(args);
1675 
1676         xs = limit(xs, 0, video_num_columns - 1);
1677         ys = limit(ys, 0, video_num_lines - 1);
1678         xe = limit(xe, 0, video_num_columns - 1);
1679         ye = limit(ye, 0, video_num_lines - 1);
1680         ps = ys * video_size_row + (xs << 1);
1681         pe = ye * video_size_row + (xe << 1);
1682 
1683         if (ps > pe)    /* make sel_start <= sel_end */
1684         {
1685                 int tmp = ps;
1686                 ps = pe;
1687                 pe = tmp;
1688         }
1689 
1690         switch (sel_mode)
1691         {
1692                 case 0: /* character-by-character selection */
1693                 default:
1694                         new_sel_start = ps;
1695                         new_sel_end = pe;
1696                         break;
1697                 case 1: /* word-by-word selection */
1698                         spc = isspace(*(off + ps));
1699                         for (new_sel_start = ps; ; ps -= 2)
1700                         {
1701                                 if ((spc && !isspace(*(off + ps))) ||
1702                                     (!spc && !inword(*(off + ps))))
1703                                         break;
1704                                 new_sel_start = ps;
1705                                 if (!(ps % video_size_row))
1706                                         break;
1707                         }
1708                         spc = isspace(*(off + pe));
1709                         for (new_sel_end = pe; ; pe += 2)
1710                         {
1711                                 if ((spc && !isspace(*(off + pe))) ||
1712                                     (!spc && !inword(*(off + pe))))
1713                                         break;
1714                                 new_sel_end = pe;
1715                                 if (!((pe + 2) % video_size_row))
1716                                         break;
1717                         }
1718                         break;
1719                 case 2: /* line-by-line selection */
1720                         new_sel_start = ps - ps % video_size_row;
1721                         new_sel_end = pe + video_size_row
1722                                     - pe % video_size_row - 2;
1723                         break;
1724         }
1725         /* select to end of line if on trailing space */
1726         if (new_sel_end > new_sel_start &&
1727                 !atedge(new_sel_end) && isspace(*(off + new_sel_end)))
1728         {
1729                 for (pe = new_sel_end + 2; ; pe += 2)
1730                 {
1731                         if (!isspace(*(off + pe)) || atedge(pe))
1732                                 break;
1733                 }
1734                 if (isspace(*(off + pe)))
1735                         new_sel_end = pe;
1736         }
1737         if (sel_cons != currcons)
1738         {
1739                 clear_selection();
1740                 sel_cons = currcons;
1741         }
1742         if (sel_start == -1)    /* no current selection */
1743                 highlight(sel_cons, new_sel_start, new_sel_end);
1744         else if (new_sel_start == sel_start)
1745         {
1746                 if (new_sel_end == sel_end)     /* no action required */
1747                         return 0;
1748                 else if (new_sel_end > sel_end) /* extend to right */
1749                         highlight(sel_cons, sel_end + 2, new_sel_end);
1750                 else                            /* contract from right */
1751                         highlight(sel_cons, new_sel_end + 2, sel_end);
1752         }
1753         else if (new_sel_end == sel_end)
1754         {
1755                 if (new_sel_start < sel_start)  /* extend to left */
1756                         highlight(sel_cons, new_sel_start, sel_start - 2);
1757                 else                            /* contract from left */
1758                         highlight(sel_cons, sel_start, new_sel_start - 2);
1759         }
1760         else    /* some other case; start selection from scratch */
1761         {
1762                 clear_selection();
1763                 highlight(sel_cons, new_sel_start, new_sel_end);
1764         }
1765         sel_start = new_sel_start;
1766         sel_end = new_sel_end;
1767         obp = bp = sel_buffer;
1768         for (i = sel_start; i <= sel_end; i += 2)
1769         {
1770                 spos = (char *)off + i;
1771                 *bp++ = *spos;
1772                 if (!isspace(*spos))
1773                         obp = bp;
1774                 if (! ((i + 2) % video_size_row))
1775                 {
1776                         /* strip trailing blanks from line and add newline,
1777                            unless non-space at end of line. */
1778                         if (obp != bp)
1779                         {
1780                                 bp = obp;
1781                                 *bp++ = '\r';
1782                         }
1783                         obp = bp;
1784                 }
1785                 /* check for space, leaving room for next character, possible
1786                    newline, and null at end. */
1787                 if (bp - sel_buffer > SEL_BUFFER_SIZE - 3)
1788                         break;
1789         }
1790         *bp = '\0';
1791         return 0;
1792 }
1793 
1794 /* insert the contents of the selection buffer into the queue of the
1795    tty associated with the current console. Invoked by ioctl(). */
1796 int paste_selection(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
1797 {
1798         char *bp = sel_buffer;
1799 
1800         if (! *bp)
1801                 return 0;
1802         unblank_screen();
1803         while (*bp) {
1804                 put_tty_queue(*bp, &tty->read_q);
1805                 bp++;
1806                 TTY_READ_FLUSH(tty);
1807         }
1808         return 0;
1809 }
1810 
1811 /* remove the current selection highlight, if any, from the console holding
1812    the selection. */
1813 static void clear_selection()
     /* [previous][next][first][last][top][bottom][index][help] */
1814 {
1815         if (sel_start != -1)
1816         {
1817                 highlight(sel_cons, sel_start, sel_end);
1818                 sel_start = -1;
1819         }
1820 }
1821 #endif /* CONFIG_SELECTION */
1822 
1823 /*
1824  * PIO_FONT support.
1825  */
1826 
1827 #define colourmap ((char *)0xa0000)
1828 #define blackwmap ((char *)0xb0000)
1829 #define cmapsz 8192
1830 #define seq_port_reg (0x3c4)
1831 #define seq_port_val (0x3c5)
1832 #define gr_port_reg (0x3ce)
1833 #define gr_port_val (0x3cf)
1834 
1835 static int set_get_font(char * arg, int set)
     /* [previous][next][first][last][top][bottom][index][help] */
1836 {
1837 #ifdef CAN_LOAD_EGA_FONTS
1838         int i;
1839         char *charmap;
1840 
1841         /* no use to "load" CGA... */
1842 
1843         if (video_type == VIDEO_TYPE_EGAC)
1844                 charmap = colourmap;
1845         else if (video_type == VIDEO_TYPE_EGAM)
1846                 charmap = blackwmap;
1847         else
1848                 return -EINVAL;
1849 
1850         i = verify_area(set ? VERIFY_READ : VERIFY_WRITE, (void *)arg, cmapsz);
1851         if (i)
1852                 return i;
1853 
1854         cli();
1855         outb_p( 0x00, seq_port_reg );   /* First, the sequencer */
1856         outb_p( 0x01, seq_port_val );   /* Synchronous reset */
1857         outb_p( 0x02, seq_port_reg );
1858         outb_p( 0x04, seq_port_val );   /* CPU writes only to map 2 */
1859         outb_p( 0x04, seq_port_reg );
1860         outb_p( 0x07, seq_port_val );   /* Sequential addressing */
1861         outb_p( 0x00, seq_port_reg );
1862         outb_p( 0x03, seq_port_val );   /* Clear synchronous reset */
1863 
1864         outb_p( 0x04, gr_port_reg );    /* Now, the graphics controller */
1865         outb_p( 0x02, gr_port_val );    /* select map 2 */
1866         outb_p( 0x05, gr_port_reg );
1867         outb_p( 0x00, gr_port_val );    /* disable odd-even addressing */
1868         outb_p( 0x06, gr_port_reg );
1869         outb_p( 0x00, gr_port_val );    /* map start at A000:0000 */
1870         sti();
1871 
1872         if (set)
1873                 for (i=0; i<cmapsz ; i++)
1874                         *(charmap+i) = get_fs_byte(arg+i);
1875         else
1876                 for (i=0; i<cmapsz ; i++)
1877                         put_fs_byte(*(charmap+i), arg+i);
1878 
1879         cli();
1880         outb_p( 0x00, seq_port_reg );   /* Frist, the sequencer */
1881         outb_p( 0x01, seq_port_val );   /* Synchronous reset */
1882         outb_p( 0x02, seq_port_reg );
1883         outb_p( 0x03, seq_port_val );   /* CPU writes to maps 0 and 1 */
1884         outb_p( 0x04, seq_port_reg );
1885         outb_p( 0x03, seq_port_val );   /* odd-even addressing */
1886         outb_p( 0x00, seq_port_reg );
1887         outb_p( 0x03, seq_port_val );   /* clear synchronous reset */
1888 
1889         outb_p( 0x04, gr_port_reg );    /* Now, the graphics controller */
1890         outb_p( 0x00, gr_port_val );    /* select map 0 for CPU */
1891         outb_p( 0x05, gr_port_reg );
1892         outb_p( 0x10, gr_port_val );    /* enable even-odd addressing */
1893         outb_p( 0x06, gr_port_reg );
1894         outb_p( 0x0e, gr_port_val );    /* map starts at b800:0000 */
1895         sti();
1896 
1897         return 0;
1898 #else
1899         return -EINVAL;
1900 #endif
1901 }
1902 
1903 /*
1904  * Load font into the EGA/VGA character generator. arg points to a 8192
1905  * byte map, 32 bytes per character. Only first H of them are used for
1906  * 8xH fonts (0 < H <= 32).
1907  */
1908 
1909 int con_set_font (char *arg)
     /* [previous][next][first][last][top][bottom][index][help] */
1910 {
1911         return set_get_font (arg,1);
1912 }
1913 
1914 int con_get_font (char *arg)
     /* [previous][next][first][last][top][bottom][index][help] */
1915 {
1916         return set_get_font (arg,0);
1917 }
1918 
1919 /*
1920  * Load customizable translation table (USER_TRANS[]). All checks are here,
1921  * so we need only include 'return con_set_trans(arg)' in the ioctl handler
1922  * arg points to a 256 byte translation table.
1923  */
1924 int con_set_trans(char * arg)
     /* [previous][next][first][last][top][bottom][index][help] */
1925 {
1926         int i;
1927 
1928         i = verify_area(VERIFY_READ, (void *)arg, E_TABSZ);
1929         if (i)
1930                 return i;
1931 
1932         for (i=0; i<E_TABSZ ; i++) USER_TRANS[i] = get_fs_byte(arg+i);
1933         USER_TRANS[012]=0;
1934         USER_TRANS[014]=0;
1935         USER_TRANS[015]=0;
1936         USER_TRANS[033]=0;
1937         return 0;
1938 }
1939 
1940 int con_get_trans(char * arg)
     /* [previous][next][first][last][top][bottom][index][help] */
1941 {
1942         int i;
1943 
1944         i = verify_area(VERIFY_WRITE, (void *)arg, E_TABSZ);
1945         if (i)
1946                 return i;
1947 
1948         for (i=0; i<E_TABSZ ; i++) put_fs_byte(USER_TRANS[i],arg+i);
1949         return 0;
1950 }

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