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) |
 628                         (color << 4)) & 0x77) << 8) | ' ';
 629         else
 630                 video_erase_char = (color << 8) | ' ';
 631 }
 632 
 633 static void default_attr(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 634 {
 635         intensity = 1;
 636         underline = 0;
 637         reverse = 0;
 638         blink = 0;
 639         color = def_color;
 640 }
 641 
 642 static void csi_m(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 643 {
 644         int i;
 645 
 646         for (i=0;i<=npar;i++)
 647                 switch (par[i]) {
 648                         case 0: /* all attributes off */
 649                                 default_attr(currcons);
 650                                 break;
 651                         case 1:
 652                                 intensity = 2;
 653                                 break;
 654                         case 2:
 655                                 intensity = 0;
 656                                 break;
 657                         case 4:
 658                                 underline = 1;
 659                                 break;
 660                         case 5:
 661                                 blink = 1;
 662                                 break;
 663                         case 7:
 664                                 reverse = 1;
 665                                 break;
 666                         case 21:
 667                         case 22:
 668                                 intensity = 1;
 669                                 break;
 670                         case 24:
 671                                 underline = 0;
 672                                 break;
 673                         case 25:
 674                                 blink = 0;
 675                                 break;
 676                         case 27:
 677                                 reverse = 0;
 678                                 break;
 679                         case 39:
 680                                 color = (def_color & 0x0f) | background;
 681                                 break;
 682                         case 49:
 683                                 color = (def_color & 0xf0) | foreground;
 684                                 break;
 685                         default:
 686                                 if (par[i] >= 30 && par[i] <= 37)
 687                                         color = color_table[par[i]-30]
 688                                                 | background; 
 689                                 else if (par[i] >= 40 && par[i] <= 47)
 690                                         color = (color_table[par[i]-40]<<4)
 691                                                 | foreground;
 692                                 break;
 693                 }
 694         update_attr(currcons);
 695 }
 696 
 697 static void respond_string(char * p, int currcons, struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 698 {
 699         while (*p) {
 700                 put_tty_queue(*p, &tty->read_q);
 701                 p++;
 702         }
 703         TTY_READ_FLUSH(tty);
 704 }
 705 
 706 static void respond_num(unsigned int n, int currcons, struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 707 {
 708         char buff[3];
 709         int i = 0;
 710 
 711         do {
 712                 buff[i++] = (n%10)+'0';
 713                 n /= 10;
 714         } while(n && i < 3);    /* We'll take no chances */
 715         while (i--) {
 716                 put_tty_queue(buff[i], &tty->read_q);
 717         }
 718         /* caller must flush */
 719 }
 720 
 721 static void cursor_report(int currcons, struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 722 {
 723         put_tty_queue('\033', &tty->read_q);
 724         put_tty_queue('[', &tty->read_q);
 725         respond_num(y + (decom ? top+1 : 1), currcons, tty);
 726         put_tty_queue(';', &tty->read_q);
 727         respond_num(x+1, currcons, tty);
 728         put_tty_queue('R', &tty->read_q);
 729         TTY_READ_FLUSH(tty);
 730 }
 731 
 732 static inline void status_report(int currcons, struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 733 {
 734         respond_string("\033[0n", currcons, tty);       /* Terminal ok */
 735 }
 736 
 737 static inline void respond_ID(int currcons, struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 738 {
 739         respond_string(VT102ID, currcons, tty);
 740 }
 741 
 742 static void invert_screen(int currcons) {
     /* [previous][next][first][last][top][bottom][index][help] */
 743         unsigned char *p;
 744 
 745         if (can_do_color)
 746                 for (p = (unsigned char *)origin+1; p < (unsigned char *)scr_end; p+=2)
 747                         *p = (*p & 0x88) | (((*p >> 4) | (*p << 4)) & 0x77);
 748         else
 749                 for (p = (unsigned char *)origin+1; p < (unsigned char *)scr_end; p+=2)
 750                         *p ^= *p & 0x07 == 1 ? 0x70 : 0x77;
 751 }
 752 
 753 static void set_mode(int currcons, int on_off)
     /* [previous][next][first][last][top][bottom][index][help] */
 754 {
 755         int i;
 756 
 757         for (i=0; i<=npar; i++)
 758                 if (ques) switch(par[i]) {      /* DEC private modes set/reset */
 759                         case 1:                 /* Cursor keys send ^[Ox/^[[x */
 760                                 if (on_off)
 761                                         set_kbd(decckm);
 762                                 else
 763                                         clr_kbd(decckm);
 764                                 break;
 765                         case 3: /* 80/132 mode switch unimplemented */
 766                                 csi_J(currcons,2);
 767                                 gotoxy(currcons,0,0);
 768                                 break;
 769                         case 5:                 /* Inverted screen on/off */
 770                                 if (decscnm != on_off) {
 771                                         decscnm = on_off;
 772                                         invert_screen(currcons);
 773                                         update_attr(currcons);
 774                                 }
 775                                 break;
 776                         case 6:                 /* Origin relative/absolute */
 777                                 decom = on_off;
 778                                 gotoxy(currcons,0,0);
 779                                 break;
 780                         case 7:                 /* Autowrap on/off */
 781                                 decawm = on_off;
 782                                 break;
 783                         case 8:                 /* Autorepeat on/off */
 784                                 if (on_off)
 785                                         set_kbd(decarm);
 786                                 else
 787                                         clr_kbd(decarm);
 788                                 break;
 789                         case 25:                /* Cursor on/off */
 790                                 deccm = on_off;
 791                                 set_cursor(currcons);
 792                                 break;
 793                 } else switch(par[i]) {         /* ANSI modes set/reset */
 794                         case 4:                 /* Insert Mode on/off */
 795                                 decim = on_off;
 796                                 break;
 797                         case 20:                /* Lf, Enter == CrLf/Lf */
 798                                 if (on_off)
 799                                         set_kbd(lnm);
 800                                 else
 801                                         clr_kbd(lnm);
 802                                 break;
 803                 }
 804 }
 805 
 806 static void setterm_command(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 807 {
 808         switch(par[0]) {
 809                 case 1: /* set color for underline mode */
 810                         if (can_do_color && par[1] < 16) {
 811                                 ulcolor = color_table[par[1]];
 812                                 if (underline)
 813                                         update_attr(currcons);
 814                         }
 815                         break;
 816                 case 2: /* set color for half intensity mode */
 817                         if (can_do_color && par[1] < 16) {
 818                                 halfcolor = color_table[par[1]];
 819                                 if (intensity == 0)
 820                                         update_attr(currcons);
 821                         }
 822                         break;
 823                 case 8: /* store colors as defaults */
 824                         def_color = attr;
 825                         default_attr(currcons);
 826                         update_attr(currcons);
 827                         break;
 828                 case 9: /* set blanking interval */
 829                         blankinterval = ((par[1] < 60) ? par[1] : 60) * 60 * HZ;
 830                         break;
 831         }
 832 }
 833 
 834 static void insert_char(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 835 {
 836         unsigned int i = x;
 837         unsigned short tmp, old = video_erase_char;
 838         unsigned short * p = (unsigned short *) pos;
 839 
 840         while (i++ < video_num_columns) {
 841                 tmp = *p;
 842                 *p = old;
 843                 old = tmp;
 844                 p++;
 845         }
 846         need_wrap = 0;
 847 }
 848 
 849 static void insert_line(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 850 {
 851         scrdown(currcons,y,bottom);
 852         need_wrap = 0;
 853 }
 854 
 855 static void delete_char(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 856 {
 857         unsigned int i = x;
 858         unsigned short * p = (unsigned short *) pos;
 859 
 860         while (++i < video_num_columns) {
 861                 *p = *(p+1);
 862                 p++;
 863         }
 864         *p = video_erase_char;
 865         need_wrap = 0;
 866 }
 867 
 868 static void delete_line(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 869 {
 870         scrup(currcons,y,bottom);
 871         need_wrap = 0;
 872 }
 873 
 874 static void csi_at(int currcons, unsigned int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
 875 {
 876         if (nr > video_num_columns)
 877                 nr = video_num_columns;
 878         else if (!nr)
 879                 nr = 1;
 880         while (nr--)
 881                 insert_char(currcons);
 882 }
 883 
 884 static void csi_L(int currcons, unsigned int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
 885 {
 886         if (nr > video_num_lines)
 887                 nr = video_num_lines;
 888         else if (!nr)
 889                 nr = 1;
 890         while (nr--)
 891                 insert_line(currcons);
 892 }
 893 
 894 static void csi_P(int currcons, unsigned int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
 895 {
 896         if (nr > video_num_columns)
 897                 nr = video_num_columns;
 898         else if (!nr)
 899                 nr = 1;
 900         while (nr--)
 901                 delete_char(currcons);
 902 }
 903 
 904 static void csi_M(int currcons, unsigned int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
 905 {
 906         if (nr > video_num_lines)
 907                 nr = video_num_lines;
 908         else if (!nr)
 909                 nr=1;
 910         while (nr--)
 911                 delete_line(currcons);
 912 }
 913 
 914 static void save_cur(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 915 {
 916         saved_x         = x;
 917         saved_y         = y;
 918         s_intensity     = intensity;
 919         s_underline     = underline;
 920         s_blink         = blink;
 921         s_reverse       = reverse;
 922         s_charset       = charset;
 923         s_color         = color;
 924         saved_G0        = G0_charset;
 925         saved_G1        = G1_charset;
 926 }
 927 
 928 static void restore_cur(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 929 {
 930         gotoxy(currcons,saved_x,saved_y);
 931         intensity       = s_intensity;
 932         underline       = s_underline;
 933         blink           = s_blink;
 934         reverse         = s_reverse;
 935         charset         = s_charset;
 936         color           = s_color;
 937         G0_charset      = saved_G0;
 938         G1_charset      = saved_G1;
 939         translate       = charset ? G1_charset : G0_charset;
 940         update_attr(currcons);
 941         need_wrap = 0;
 942 }
 943 
 944 enum { ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey, 
 945         EShash, ESsetG0, ESsetG1, ESignore };
 946 
 947 static void reset_terminal(int currcons, int do_clear)
     /* [previous][next][first][last][top][bottom][index][help] */
 948 {
 949         top             = 0;
 950         bottom          = video_num_lines;
 951         state           = ESnormal;
 952         ques            = 0;
 953         translate       = NORM_TRANS;
 954         G0_charset      = NORM_TRANS;
 955         G1_charset      = GRAF_TRANS;
 956         charset         = 0;
 957         need_wrap       = 0;
 958 
 959         decscnm         = 0;
 960         decom           = 0;
 961         decawm          = 1;
 962         deccm           = 1;
 963         decim           = 0;
 964 
 965         set_kbd(decarm);
 966         clr_kbd(decckm);
 967         clr_kbd(kbdapplic);
 968         clr_kbd(lnm);
 969         kbd_table[currcons].lockstate = 0;
 970         kbd_table[currcons].ledstate = kbd_table[currcons].default_ledstate;
 971         set_leds();
 972 
 973         default_attr(currcons);
 974         update_attr(currcons);
 975 
 976         tab_stop[0]     = 0x01010100;
 977         tab_stop[1]     =
 978         tab_stop[2]     =
 979         tab_stop[3]     =
 980         tab_stop[4]     = 0x01010101;
 981 
 982         if (do_clear) {
 983                 gotoxy(currcons,0,0);
 984                 csi_J(currcons,2);
 985                 save_cur(currcons);
 986         }
 987 }
 988 
 989 void con_write(struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 990 {
 991         int c;
 992         unsigned int currcons;
 993 
 994         currcons = tty->line - 1;
 995         if (currcons >= NR_CONSOLES) {
 996                 printk("con_write: illegal tty (%d)\n", currcons);
 997                 return;
 998         }
 999 #ifdef CONFIG_SELECTION
1000         /* clear the selection as soon as any characters are to be written
1001            out on the console holding the selection. */
1002         if (!EMPTY(&tty->write_q) && currcons == sel_cons)
1003                 clear_selection();
1004 #endif /* CONFIG_SELECTION */
1005         disable_bh(KEYBOARD_BH);
1006         while (!tty->stopped && (c = get_tty_queue(&tty->write_q)) >= 0) {
1007                 if (state == ESnormal && translate[c]) {
1008                         if (need_wrap) {
1009                                 cr(currcons);
1010                                 lf(currcons);
1011                         }
1012                         if (decim)
1013                                 insert_char(currcons);
1014                         c = translate[c];
1015                         *(unsigned short *) pos = (attr << 8) + c;
1016                         if (x == video_num_columns - 1)
1017                                 need_wrap = decawm;
1018                         else {
1019                                 x++;
1020                                 pos+=2;
1021                         }
1022                         continue;
1023                 }
1024 
1025                 /*
1026                  *  Control characters can be used in the _middle_
1027                  *  of an escape sequence.
1028                  */
1029                 switch (c) {
1030                         case 7:
1031                                 kd_mksound(0x637, HZ/8);
1032                                 continue;
1033                         case 8:
1034                                 bs(currcons);
1035                                 continue;
1036                         case 9:
1037                                 pos -= (x << 1);
1038                                 while (x < video_num_columns - 1) {
1039                                         x++;
1040                                         if (tab_stop[x >> 5] & (1 << (x & 31)))
1041                                                 break;
1042                                 }
1043                                 pos += (x << 1);
1044                                 continue;
1045                         case 10: case 11: case 12:
1046                                 lf(currcons);
1047                                 if (!is_kbd(lnm))
1048                                         continue;
1049                         case 13:
1050                                 cr(currcons);
1051                                 continue;
1052                         case 14:
1053                                 charset = 1;
1054                                 translate = G1_charset;
1055                                 continue;
1056                         case 15:
1057                                 charset = 0;
1058                                 translate = G0_charset;
1059                                 continue;
1060                         case 24: case 26:
1061                                 state = ESnormal;
1062                                 continue;
1063                         case 27:
1064                                 state = ESesc;
1065                                 continue;
1066                         case 127:
1067                                 del(currcons);
1068                                 continue;
1069                         case 128+27:
1070                                 state = ESsquare;
1071                                 continue;
1072                 }
1073                 switch(state) {
1074                         case ESesc:
1075                                 state = ESnormal;
1076                                 switch (c) {
1077                                   case '[':
1078                                         state = ESsquare;
1079                                         continue;
1080                                   case 'E':
1081                                         cr(currcons);
1082                                         lf(currcons);
1083                                         continue;
1084                                   case 'M':
1085                                         ri(currcons);
1086                                         continue;
1087                                   case 'D':
1088                                         lf(currcons);
1089                                         continue;
1090                                   case 'H':
1091                                         tab_stop[x >> 5] |= (1 << (x & 31));
1092                                         continue;
1093                                   case 'Z':
1094                                         respond_ID(currcons,tty);
1095                                         continue;
1096                                   case '7':
1097                                         save_cur(currcons);
1098                                         continue;
1099                                   case '8':
1100                                         restore_cur(currcons);
1101                                         continue;
1102                                   case '(':
1103                                         state = ESsetG0;
1104                                         continue;
1105                                   case ')':
1106                                         state = ESsetG1;
1107                                         continue;
1108                                   case '#':
1109                                         state = EShash;
1110                                         continue;
1111                                   case 'c':
1112                                         reset_terminal(currcons,1);
1113                                         continue;
1114                                   case '>':  /* Numeric keypad */
1115                                         clr_kbd(kbdapplic);
1116                                         continue;
1117                                   case '=':  /* Appl. keypad */
1118                                         set_kbd(kbdapplic);
1119                                         continue;
1120                                 }       
1121                                 continue;
1122                         case ESsquare:
1123                                 for(npar = 0 ; npar < NPAR ; npar++)
1124                                         par[npar] = 0;
1125                                 npar = 0;
1126                                 state = ESgetpars;
1127                                 if (c == '[') { /* Function key */
1128                                         state=ESfunckey;
1129                                         continue;
1130                                 }
1131                                 ques = (c=='?');
1132                                 if (ques)
1133                                         continue;
1134                         case ESgetpars:
1135                                 if (c==';' && npar<NPAR-1) {
1136                                         npar++;
1137                                         continue;
1138                                 } else if (c>='0' && c<='9') {
1139                                         par[npar] *= 10;
1140                                         par[npar] += c-'0';
1141                                         continue;
1142                                 } else state=ESgotpars;
1143                         case ESgotpars:
1144                                 state = ESnormal;
1145                                 switch(c) {
1146                                         case 'h':
1147                                                 set_mode(currcons,1);
1148                                                 continue;
1149                                         case 'l':
1150                                                 set_mode(currcons,0);
1151                                                 continue;
1152                                         case 'n':
1153                                                 if (!ques)
1154                                                         if (par[0] == 5)
1155                                                                 status_report(currcons,tty);
1156                                                         else if (par[0] == 6)
1157                                                                 cursor_report(currcons,tty);
1158                                                 continue;
1159                                 }
1160                                 if (ques) {
1161                                         ques = 0;
1162                                         continue;
1163                                 }
1164                                 switch(c) {
1165                                         case 'G': case '`':
1166                                                 if (par[0]) par[0]--;
1167                                                 gotoxy(currcons,par[0],y);
1168                                                 continue;
1169                                         case 'A':
1170                                                 if (!par[0]) par[0]++;
1171                                                 gotoxy(currcons,x,y-par[0]);
1172                                                 continue;
1173                                         case 'B': case 'e':
1174                                                 if (!par[0]) par[0]++;
1175                                                 gotoxy(currcons,x,y+par[0]);
1176                                                 continue;
1177                                         case 'C': case 'a':
1178                                                 if (!par[0]) par[0]++;
1179                                                 gotoxy(currcons,x+par[0],y);
1180                                                 continue;
1181                                         case 'D':
1182                                                 if (!par[0]) par[0]++;
1183                                                 gotoxy(currcons,x-par[0],y);
1184                                                 continue;
1185                                         case 'E':
1186                                                 if (!par[0]) par[0]++;
1187                                                 gotoxy(currcons,0,y+par[0]);
1188                                                 continue;
1189                                         case 'F':
1190                                                 if (!par[0]) par[0]++;
1191                                                 gotoxy(currcons,0,y-par[0]);
1192                                                 continue;
1193                                         case 'd':
1194                                                 if (par[0]) par[0]--;
1195                                                 gotoxy(currcons,x,par[0]);
1196                                                 continue;
1197                                         case 'H': case 'f':
1198                                                 if (par[0]) par[0]--;
1199                                                 if (par[1]) par[1]--;
1200                                                 gotoxy(currcons,par[1],par[0]);
1201                                                 continue;
1202                                         case 'J':
1203                                                 csi_J(currcons,par[0]);
1204                                                 continue;
1205                                         case 'K':
1206                                                 csi_K(currcons,par[0]);
1207                                                 continue;
1208                                         case 'L':
1209                                                 csi_L(currcons,par[0]);
1210                                                 continue;
1211                                         case 'M':
1212                                                 csi_M(currcons,par[0]);
1213                                                 continue;
1214                                         case 'P':
1215                                                 csi_P(currcons,par[0]);
1216                                                 continue;
1217                                         case 'c':
1218                                                 if (!par[0])
1219                                                         respond_ID(currcons,tty);
1220                                                 continue;
1221                                         case 'g':
1222                                                 if (!par[0])
1223                                                         tab_stop[x >> 5] &= ~(1 << (x & 31));
1224                                                 else if (par[0] == 3) {
1225                                                         tab_stop[0] =
1226                                                         tab_stop[1] =
1227                                                         tab_stop[2] =
1228                                                         tab_stop[3] =
1229                                                         tab_stop[4] = 0;
1230                                                 }
1231                                                 continue;
1232                                         case 'm':
1233                                                 csi_m(currcons);
1234                                                 continue;
1235                                         case 'r':
1236                                                 if (!par[0])
1237                                                         par[0]++;
1238                                                 if (!par[1])
1239                                                         par[1] = video_num_lines;
1240                                                 /* Minimum allowed region is 2 lines */
1241                                                 if (par[0] < par[1] &&
1242                                                     par[1] <= video_num_lines) {
1243                                                         top=par[0]-1;
1244                                                         bottom=par[1];
1245                                                         gotoxy(currcons,0,0);
1246                                                 }
1247                                                 continue;
1248                                         case 's':
1249                                                 save_cur(currcons);
1250                                                 continue;
1251                                         case 'u':
1252                                                 restore_cur(currcons);
1253                                                 continue;
1254                                         case '@':
1255                                                 csi_at(currcons,par[0]);
1256                                                 continue;
1257                                         case ']': /* setterm functions */
1258                                                 setterm_command(currcons);
1259                                                 continue;
1260                                 }
1261                                 continue;
1262                         case ESfunckey:
1263                                 state = ESnormal;
1264                                 continue;
1265                         case EShash:
1266                                 state = ESnormal;
1267                                 if (c == '8') {
1268                                         /* DEC screen alignment test. kludge :-) */
1269                                         video_erase_char =
1270                                                 (video_erase_char & 0xff00) | 'E';
1271                                         csi_J(currcons, 2);
1272                                         video_erase_char =
1273                                                 (video_erase_char & 0xff00) | ' ';
1274                                 }
1275                                 continue;
1276                         case ESsetG0:
1277                                 if (c == '0')
1278                                         G0_charset = GRAF_TRANS;
1279                                 else if (c == 'B')
1280                                         G0_charset = NORM_TRANS;
1281                                 else if (c == 'U')
1282                                         G0_charset = NULL_TRANS;
1283                                 else if (c == 'K')
1284                                         G0_charset = USER_TRANS;
1285                                 if (charset == 0)
1286                                         translate = G0_charset;
1287                                 state = ESnormal;
1288                                 continue;
1289                         case ESsetG1:
1290                                 if (c == '0')
1291                                         G1_charset = GRAF_TRANS;
1292                                 else if (c == 'B')
1293                                         G1_charset = NORM_TRANS;
1294                                 else if (c == 'U')
1295                                         G1_charset = NULL_TRANS;
1296                                 else if (c == 'K')
1297                                         G1_charset = USER_TRANS;
1298                                 if (charset == 1)
1299                                         translate = G1_charset;
1300                                 state = ESnormal;
1301                                 continue;
1302                         default:
1303                                 state = ESnormal;
1304                 }
1305         }
1306         if (vcmode != KD_GRAPHICS)
1307                 set_cursor(currcons);
1308         enable_bh(KEYBOARD_BH);
1309         if (LEFT(&tty->write_q) > WAKEUP_CHARS)
1310                 wake_up_interruptible(&tty->write_q.proc_list);
1311 }
1312 
1313 void do_keyboard_interrupt(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1314 {
1315         TTY_READ_FLUSH(TTY_TABLE(0));
1316         timer_active &= ~(1<<BLANK_TIMER);
1317         if (vt_cons[fg_console].vc_mode == KD_GRAPHICS)
1318                 return;
1319         if (console_blanked) {
1320                 timer_table[BLANK_TIMER].expires = 0;
1321                 timer_active |= 1<<BLANK_TIMER;
1322         } else if (blankinterval) {
1323                 timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
1324                 timer_active |= 1<<BLANK_TIMER;
1325         }
1326 }
1327 
1328 void * memsetw(void * s,unsigned short c,int count)
     /* [previous][next][first][last][top][bottom][index][help] */
1329 {
1330 __asm__("cld\n\t"
1331         "rep\n\t"
1332         "stosw"
1333         : /* no output */
1334         :"a" (c),"D" (s),"c" (count)
1335         :"cx","di");
1336 return s;
1337 }
1338 
1339 void console_print(const char * b)
     /* [previous][next][first][last][top][bottom][index][help] */
1340 {
1341         int currcons = fg_console;
1342         unsigned char c;
1343 
1344         if (!printable || currcons<0 || currcons>=NR_CONSOLES)
1345                 return;
1346         while ((c = *(b++)) != 0) {
1347                 if (c == 10 || c == 13 || need_wrap) {
1348                         if (c != 13)
1349                                 lf(currcons);
1350                         cr(currcons);
1351                         if (c == 10 || c == 13)
1352                                 continue;
1353                 }
1354                 *(unsigned short *) pos = (attr << 8) + c;
1355                 if (x == video_num_columns - 1) {
1356                         need_wrap = 1;
1357                         continue;
1358                 }
1359                 x++;
1360                 pos+=2;
1361         }
1362         set_cursor(currcons);
1363         if (vt_cons[fg_console].vc_mode == KD_GRAPHICS)
1364                 return;
1365         timer_active &= ~(1<<BLANK_TIMER);
1366         if (console_blanked) {
1367                 timer_table[BLANK_TIMER].expires = 0;
1368                 timer_active |= 1<<BLANK_TIMER;
1369         } else if (blankinterval) {
1370                 timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
1371                 timer_active |= 1<<BLANK_TIMER;
1372         }
1373 }
1374 
1375 /*
1376  *  long con_init(long);
1377  *
1378  * This routine initalizes console interrupts, and does nothing
1379  * else. If you want the screen to clear, call tty_write with
1380  * the appropriate escape-sequece.
1381  *
1382  * Reads the information preserved by setup.s to determine the current display
1383  * type and sets everything accordingly.
1384  */
1385 long con_init(long kmem_start)
     /* [previous][next][first][last][top][bottom][index][help] */
1386 {
1387         char *display_desc = "????";
1388         int currcons = 0;
1389         long base;
1390         int orig_x = ORIG_X;
1391         int orig_y = ORIG_Y;
1392 
1393         vc_scrmembuf = (unsigned short *) kmem_start;
1394         video_num_columns = ORIG_VIDEO_COLS;
1395         video_size_row = video_num_columns * 2;
1396         video_num_lines = ORIG_VIDEO_LINES;
1397         video_page = ORIG_VIDEO_PAGE;
1398         screen_size = (video_num_lines * video_size_row);
1399         kmem_start += NR_CONSOLES * screen_size;
1400         timer_table[BLANK_TIMER].fn = blank_screen;
1401         timer_table[BLANK_TIMER].expires = 0;
1402         if (blankinterval) {
1403                 timer_table[BLANK_TIMER].expires = jiffies+blankinterval;
1404                 timer_active |= 1<<BLANK_TIMER;
1405         }
1406         
1407         if (ORIG_VIDEO_MODE == 7)       /* Is this a monochrome display? */
1408         {
1409                 video_mem_base = 0xb0000;
1410                 video_port_reg = 0x3b4;
1411                 video_port_val = 0x3b5;
1412                 if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
1413                 {
1414                         video_type = VIDEO_TYPE_EGAM;
1415                         video_mem_term = 0xb8000;
1416                         display_desc = "EGA+";
1417                 }
1418                 else
1419                 {
1420                         video_type = VIDEO_TYPE_MDA;
1421                         video_mem_term = 0xb2000;
1422                         display_desc = "*MDA";
1423                 }
1424         }
1425         else                            /* If not, it is color. */
1426         {
1427                 can_do_color = 1;
1428                 video_mem_base = 0xb8000;
1429                 video_port_reg  = 0x3d4;
1430                 video_port_val  = 0x3d5;
1431                 if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
1432                 {
1433                         video_type = VIDEO_TYPE_EGAC;
1434                         video_mem_term = 0xc0000;
1435                         display_desc = "EGA+";
1436                 }
1437                 else
1438                 {
1439                         video_type = VIDEO_TYPE_CGA;
1440                         video_mem_term = 0xba000;
1441                         display_desc = "*CGA";
1442                 }
1443         }
1444         
1445         /* Initialize the variables used for scrolling (mostly EGA/VGA) */
1446 
1447         base = (long)vc_scrmembuf;
1448         for (currcons = 0; currcons<NR_CONSOLES; currcons++) {
1449                 pos = origin = video_mem_start = base;
1450                 scr_end = video_mem_end = (base += screen_size);
1451                 vc_scrbuf[currcons] = (unsigned short *) origin;
1452                 vcmode          = KD_TEXT;
1453                 vtmode.mode     = VT_AUTO;
1454                 vtmode.waitv    = 0;
1455                 vtmode.relsig   = 0;
1456                 vtmode.acqsig   = 0;
1457                 vtmode.frsig    = 0;
1458                 vtpid           = -1;
1459                 vtnewvt         = -1;
1460                 clr_kbd(kbdraw);
1461                 def_color       = 0x07;   /* white */
1462                 ulcolor         = 0x0f;   /* bold white */
1463                 halfcolor       = 0x08;   /* grey */
1464                 reset_terminal(currcons, currcons);
1465         }
1466         currcons = fg_console = 0;
1467 
1468         video_mem_start = video_mem_base;
1469         video_mem_end = video_mem_term;
1470         origin = video_mem_start;
1471         scr_end = video_mem_start + video_num_lines * video_size_row;
1472         gotoxy(currcons,0,0);
1473         save_cur(currcons);
1474         gotoxy(currcons,orig_x,orig_y);
1475         update_screen(fg_console);
1476         printable = 1;
1477         printk("Console: %s %s %ldx%ld, %d virtual consoles\n",
1478                 can_do_color?"colour":"mono",
1479                 display_desc,
1480                 video_num_columns,video_num_lines,
1481                 NR_CONSOLES);
1482         register_console(console_print);
1483         return kmem_start;
1484 }
1485 
1486 /*
1487  * kbdsave doesn't need to do anything: it's all handled automatically
1488  * with the new data structures..
1489  */
1490 void kbdsave(int new_console)
     /* [previous][next][first][last][top][bottom][index][help] */
1491 {
1492 }
1493 
1494 static void get_scrmem(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
1495 {
1496         memcpy((void *)vc_scrbuf[currcons],(void *)origin, screen_size);
1497         video_mem_start = (unsigned long)vc_scrbuf[currcons];
1498         origin  = video_mem_start;
1499         scr_end = video_mem_end = video_mem_start+screen_size;
1500         pos = origin + y*video_size_row + (x<<1);
1501 }
1502 
1503 static void set_scrmem(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
1504 {
1505 #ifdef CONFIG_HGA
1506   /* This works with XFree86 1.2, 1.3 and 2.0
1507      This code could be extended and made more generally useful if we could
1508      determine the actual video mode. It appears that this should be
1509      possible on a genuine Hercules card, but I (WM) haven't been able to
1510      read from any of the required registers on my clone card.
1511      */
1512         /* This code should work with Hercules and MDA cards. */
1513         if (video_type == VIDEO_TYPE_MDA)
1514           {
1515             if (vcmode == KD_TEXT)
1516               {
1517                 /* Ensure that the card is in text mode. */
1518                 int     i;
1519                 static char herc_txt_tbl[12] = {
1520                   0x61,0x50,0x52,0x0f,0x19,6,0x19,0x19,2,0x0d,0x0b,0x0c };
1521                 outb_p(0, 0x3bf);  /* Back to power-on defaults */
1522                 outb_p(0, 0x3b8);  /* Blank the screen, select page 0, etc */
1523                 for ( i = 0 ; i < 12 ; i++ )
1524                   {
1525                     outb_p(i, 0x3b4);
1526                     outb_p(herc_txt_tbl[i], 0x3b5);
1527                   }
1528               }
1529 #define HGA_BLINKER_ON 0x20
1530 #define HGA_SCREEN_ON  8
1531             /* Make sure that the hardware is not blanked */
1532             outb_p(HGA_BLINKER_ON | HGA_SCREEN_ON, 0x3b8);
1533           }
1534 #endif CONFIG_HGA
1535 
1536         video_mem_start = video_mem_base;
1537         video_mem_end = video_mem_term;
1538         origin  = video_mem_start;
1539         scr_end = video_mem_start + screen_size;
1540         pos = origin + y*video_size_row + (x<<1);
1541         memcpy((void *)video_mem_base, (void *)vc_scrbuf[fg_console], screen_size);
1542 }
1543 
1544 void blank_screen(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1545 {
1546         if (console_blanked)
1547                 return;
1548         timer_table[BLANK_TIMER].fn = unblank_screen;
1549         get_scrmem(fg_console);
1550         hide_cursor(fg_console);
1551         console_blanked = 1;
1552         memsetw((void *)video_mem_base, 0x0020, video_mem_term-video_mem_base );
1553 }
1554 
1555 void unblank_screen(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1556 {
1557         if (!console_blanked)
1558                 return;
1559         timer_table[BLANK_TIMER].fn = blank_screen;
1560         if (blankinterval) {
1561                 timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
1562                 timer_active |= 1<<BLANK_TIMER;
1563         }
1564         console_blanked = 0;
1565         set_scrmem(fg_console);
1566         set_origin(fg_console);
1567         set_cursor(fg_console);
1568 }
1569 
1570 void update_screen(int new_console)
     /* [previous][next][first][last][top][bottom][index][help] */
1571 {
1572         static int lock = 0;
1573 
1574         if (new_console == fg_console || lock)
1575                 return;
1576         lock = 1;
1577         kbdsave(new_console);
1578         get_scrmem(fg_console); 
1579         fg_console = new_console;
1580         set_scrmem(fg_console); 
1581         set_origin(fg_console);
1582         set_cursor(new_console);
1583         set_leds();
1584         compute_shiftstate();
1585         lock = 0;
1586 }
1587 
1588 int do_screendump(int arg)
     /* [previous][next][first][last][top][bottom][index][help] */
1589 {
1590         char *sptr, *buf = (char *)arg;
1591         int currcons, l;
1592 
1593         if (!suser())
1594                 return -EPERM;
1595         l = verify_area(VERIFY_WRITE, buf,2+video_num_columns*video_num_lines);
1596         if (l)
1597                 return l;
1598         currcons = get_fs_byte(buf+1);
1599         if ((currcons<0) || (currcons>NR_CONSOLES))
1600                 return -EIO;
1601         put_fs_byte((char)(video_num_lines),buf++);     
1602         put_fs_byte((char)(video_num_columns),buf++);
1603         currcons = (currcons ? currcons-1 : fg_console);
1604         sptr = (char *) origin;
1605         for (l=video_num_lines*video_num_columns; l>0 ; l--, sptr++)
1606                 put_fs_byte(*sptr++,buf++);     
1607         return(0);
1608 }
1609 
1610 /*
1611  * All we do is set the write and ioctl subroutines; later on maybe we'll
1612  * dynamically allocate the console screen memory.
1613  */
1614 int con_open(struct tty_struct *tty, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
1615 {
1616         tty->write = con_write;
1617         tty->ioctl = vt_ioctl;
1618         if (tty->line > NR_CONSOLES)
1619                 return -ENODEV;
1620         return 0;
1621 }
1622 
1623 #ifdef CONFIG_SELECTION
1624 /* correction factor for when screen is hardware-scrolled */
1625 #define hwscroll_offset (currcons == fg_console ? ((__real_origin - __origin) << 1) : 0)
1626 
1627 /* set reverse video on characters s-e of console with selection. */
1628 static void highlight(const int currcons, const int s, const int e)
     /* [previous][next][first][last][top][bottom][index][help] */
1629 {
1630         unsigned char *p, *p1, *p2;
1631 
1632         p1 = (unsigned char *)origin - hwscroll_offset + s + 1;
1633         p2 = (unsigned char *)origin - hwscroll_offset + e + 1;
1634         if (p1 > p2)
1635         {
1636                 p = p1;
1637                 p1 = p2;
1638                 p2 = p;
1639         }
1640         for (p = p1; p <= p2; p += 2)
1641                 *p = (*p & 0x88) | ((*p << 4) & 0x70) | ((*p >> 4) & 0x07);
1642 }
1643 
1644 /* is c in range [a-zA-Z0-9_]? */
1645 static inline int inword(const char c) { return (isalnum(c) || c == '_'); }
     /* [previous][next][first][last][top][bottom][index][help] */
1646 
1647 /* does screen address p correspond to character at LH/RH edge of screen? */
1648 static inline int atedge(const int p)
     /* [previous][next][first][last][top][bottom][index][help] */
1649 {
1650         return (!(p % video_size_row) || !((p + 2) % video_size_row));
1651 }
1652 
1653 /* constrain v such that l <= v <= u */
1654 static inline short limit(const int v, const int l, const int u)
     /* [previous][next][first][last][top][bottom][index][help] */
1655 {
1656         return (v < l) ? l : ((v > u) ? u : v);
1657 }
1658 
1659 /* set the current selection. Invoked by ioctl(). */
1660 int set_selection(const int arg)
     /* [previous][next][first][last][top][bottom][index][help] */
1661 {
1662         unsigned short *args, xs, ys, xe, ye;
1663         int currcons = fg_console;
1664         int sel_mode, new_sel_start, new_sel_end, spc;
1665         char *bp, *obp, *spos;
1666         int i, ps, pe;
1667         char *off = (char *)origin - hwscroll_offset;
1668 
1669         unblank_screen();
1670         args = (unsigned short *)(arg + 1);
1671         xs = get_fs_word(args++) - 1;
1672         ys = get_fs_word(args++) - 1;
1673         xe = get_fs_word(args++) - 1;
1674         ye = get_fs_word(args++) - 1;
1675         sel_mode = get_fs_word(args);
1676 
1677         xs = limit(xs, 0, video_num_columns - 1);
1678         ys = limit(ys, 0, video_num_lines - 1);
1679         xe = limit(xe, 0, video_num_columns - 1);
1680         ye = limit(ye, 0, video_num_lines - 1);
1681         ps = ys * video_size_row + (xs << 1);
1682         pe = ye * video_size_row + (xe << 1);
1683 
1684         if (ps > pe)    /* make sel_start <= sel_end */
1685         {
1686                 int tmp = ps;
1687                 ps = pe;
1688                 pe = tmp;
1689         }
1690 
1691         switch (sel_mode)
1692         {
1693                 case 0: /* character-by-character selection */
1694                 default:
1695                         new_sel_start = ps;
1696                         new_sel_end = pe;
1697                         break;
1698                 case 1: /* word-by-word selection */
1699                         spc = isspace(*(off + ps));
1700                         for (new_sel_start = ps; ; ps -= 2)
1701                         {
1702                                 if ((spc && !isspace(*(off + ps))) ||
1703                                     (!spc && !inword(*(off + ps))))
1704                                         break;
1705                                 new_sel_start = ps;
1706                                 if (!(ps % video_size_row))
1707                                         break;
1708                         }
1709                         spc = isspace(*(off + pe));
1710                         for (new_sel_end = pe; ; pe += 2)
1711                         {
1712                                 if ((spc && !isspace(*(off + pe))) ||
1713                                     (!spc && !inword(*(off + pe))))
1714                                         break;
1715                                 new_sel_end = pe;
1716                                 if (!((pe + 2) % video_size_row))
1717                                         break;
1718                         }
1719                         break;
1720                 case 2: /* line-by-line selection */
1721                         new_sel_start = ps - ps % video_size_row;
1722                         new_sel_end = pe + video_size_row
1723                                     - pe % video_size_row - 2;
1724                         break;
1725         }
1726         /* select to end of line if on trailing space */
1727         if (new_sel_end > new_sel_start &&
1728                 !atedge(new_sel_end) && isspace(*(off + new_sel_end)))
1729         {
1730                 for (pe = new_sel_end + 2; ; pe += 2)
1731                 {
1732                         if (!isspace(*(off + pe)) || atedge(pe))
1733                                 break;
1734                 }
1735                 if (isspace(*(off + pe)))
1736                         new_sel_end = pe;
1737         }
1738         if (sel_cons != currcons)
1739         {
1740                 clear_selection();
1741                 sel_cons = currcons;
1742         }
1743         if (sel_start == -1)    /* no current selection */
1744                 highlight(sel_cons, new_sel_start, new_sel_end);
1745         else if (new_sel_start == sel_start)
1746         {
1747                 if (new_sel_end == sel_end)     /* no action required */
1748                         return 0;
1749                 else if (new_sel_end > sel_end) /* extend to right */
1750                         highlight(sel_cons, sel_end + 2, new_sel_end);
1751                 else                            /* contract from right */
1752                         highlight(sel_cons, new_sel_end + 2, sel_end);
1753         }
1754         else if (new_sel_end == sel_end)
1755         {
1756                 if (new_sel_start < sel_start)  /* extend to left */
1757                         highlight(sel_cons, new_sel_start, sel_start - 2);
1758                 else                            /* contract from left */
1759                         highlight(sel_cons, sel_start, new_sel_start - 2);
1760         }
1761         else    /* some other case; start selection from scratch */
1762         {
1763                 clear_selection();
1764                 highlight(sel_cons, new_sel_start, new_sel_end);
1765         }
1766         sel_start = new_sel_start;
1767         sel_end = new_sel_end;
1768         obp = bp = sel_buffer;
1769         for (i = sel_start; i <= sel_end; i += 2)
1770         {
1771                 spos = (char *)off + i;
1772                 *bp++ = *spos;
1773                 if (!isspace(*spos))
1774                         obp = bp;
1775                 if (! ((i + 2) % video_size_row))
1776                 {
1777                         /* strip trailing blanks from line and add newline,
1778                            unless non-space at end of line. */
1779                         if (obp != bp)
1780                         {
1781                                 bp = obp;
1782                                 *bp++ = '\r';
1783                         }
1784                         obp = bp;
1785                 }
1786                 /* check for space, leaving room for next character, possible
1787                    newline, and null at end. */
1788                 if (bp - sel_buffer > SEL_BUFFER_SIZE - 3)
1789                         break;
1790         }
1791         *bp = '\0';
1792         return 0;
1793 }
1794 
1795 /* insert the contents of the selection buffer into the queue of the
1796    tty associated with the current console. Invoked by ioctl(). */
1797 int paste_selection(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
1798 {
1799         char *bp = sel_buffer;
1800 
1801         if (! *bp)
1802                 return 0;
1803         unblank_screen();
1804         while (*bp)
1805         {
1806                 put_tty_queue(*bp, &tty->read_q);
1807                 bp++;
1808         }
1809         TTY_READ_FLUSH(tty);
1810         return 0;
1811 }
1812 
1813 /* remove the current selection highlight, if any, from the console holding
1814    the selection. */
1815 static void clear_selection()
     /* [previous][next][first][last][top][bottom][index][help] */
1816 {
1817         if (sel_start != -1)
1818         {
1819                 highlight(sel_cons, sel_start, sel_end);
1820                 sel_start = -1;
1821         }
1822 }
1823 #endif /* CONFIG_SELECTION */
1824 
1825 /*
1826  * PIO_FONT support.
1827  */
1828 
1829 #define colourmap ((char *)0xa0000)
1830 #define blackwmap ((char *)0xb0000)
1831 #define cmapsz 8192
1832 #define seq_port_reg (0x3c4)
1833 #define seq_port_val (0x3c5)
1834 #define gr_port_reg (0x3ce)
1835 #define gr_port_val (0x3cf)
1836 
1837 static int set_get_font(char * arg, int set)
     /* [previous][next][first][last][top][bottom][index][help] */
1838 {
1839 #ifdef CAN_LOAD_EGA_FONTS
1840         int i;
1841         char *charmap;
1842 
1843         /* no use to "load" CGA... */
1844 
1845         if (video_type == VIDEO_TYPE_EGAC)
1846                 charmap = colourmap;
1847         else if (video_type == VIDEO_TYPE_EGAM)
1848                 charmap = blackwmap;
1849         else
1850                 return -EINVAL;
1851 
1852         i = verify_area(set ? VERIFY_READ : VERIFY_WRITE, (void *)arg, cmapsz);
1853         if (i)
1854                 return i;
1855 
1856         cli();
1857         outb_p( 0x00, seq_port_reg );   /* First, the sequencer */
1858         outb_p( 0x01, seq_port_val );   /* Synchronous reset */
1859         outb_p( 0x02, seq_port_reg );
1860         outb_p( 0x04, seq_port_val );   /* CPU writes only to map 2 */
1861         outb_p( 0x04, seq_port_reg );
1862         outb_p( 0x07, seq_port_val );   /* Sequential addressing */
1863         outb_p( 0x00, seq_port_reg );
1864         outb_p( 0x03, seq_port_val );   /* Clear synchronous reset */
1865 
1866         outb_p( 0x04, gr_port_reg );    /* Now, the graphics controller */
1867         outb_p( 0x02, gr_port_val );    /* select map 2 */
1868         outb_p( 0x05, gr_port_reg );
1869         outb_p( 0x00, gr_port_val );    /* disable odd-even addressing */
1870         outb_p( 0x06, gr_port_reg );
1871         outb_p( 0x00, gr_port_val );    /* map start at A000:0000 */
1872         sti();
1873 
1874         if (set)
1875                 for (i=0; i<cmapsz ; i++)
1876                         *(charmap+i) = get_fs_byte(arg+i);
1877         else
1878                 for (i=0; i<cmapsz ; i++)
1879                         put_fs_byte(*(charmap+i), arg+i);
1880 
1881         cli();
1882         outb_p( 0x00, seq_port_reg );   /* Frist, the sequencer */
1883         outb_p( 0x01, seq_port_val );   /* Synchronous reset */
1884         outb_p( 0x02, seq_port_reg );
1885         outb_p( 0x03, seq_port_val );   /* CPU writes to maps 0 and 1 */
1886         outb_p( 0x04, seq_port_reg );
1887         outb_p( 0x03, seq_port_val );   /* odd-even addressing */
1888         outb_p( 0x00, seq_port_reg );
1889         outb_p( 0x03, seq_port_val );   /* clear synchronous reset */
1890 
1891         outb_p( 0x04, gr_port_reg );    /* Now, the graphics controller */
1892         outb_p( 0x00, gr_port_val );    /* select map 0 for CPU */
1893         outb_p( 0x05, gr_port_reg );
1894         outb_p( 0x10, gr_port_val );    /* enable even-odd addressing */
1895         outb_p( 0x06, gr_port_reg );
1896         outb_p( 0x0e, gr_port_val );    /* map starts at b800:0000 */
1897         sti();
1898 
1899         return 0;
1900 #else
1901         return -EINVAL;
1902 #endif
1903 }
1904 
1905 /*
1906  * Load font into the EGA/VGA character generator. arg points to a 8192
1907  * byte map, 32 bytes per character. Only first H of them are used for
1908  * 8xH fonts (0 < H <= 32).
1909  */
1910 
1911 int con_set_font (char *arg)
     /* [previous][next][first][last][top][bottom][index][help] */
1912 {
1913         return set_get_font (arg,1);
1914 }
1915 
1916 int con_get_font (char *arg)
     /* [previous][next][first][last][top][bottom][index][help] */
1917 {
1918         return set_get_font (arg,0);
1919 }
1920 
1921 /*
1922  * Load customizable translation table (USER_TRANS[]). All checks are here,
1923  * so we need only include 'return con_set_trans(arg)' in the ioctl handler
1924  * arg points to a 256 byte translation table.
1925  */
1926 int con_set_trans(char * arg)
     /* [previous][next][first][last][top][bottom][index][help] */
1927 {
1928         int i;
1929 
1930         i = verify_area(VERIFY_READ, (void *)arg, E_TABSZ);
1931         if (i)
1932                 return i;
1933 
1934         for (i=0; i<E_TABSZ ; i++) USER_TRANS[i] = get_fs_byte(arg+i);
1935         USER_TRANS[012]=0;
1936         USER_TRANS[014]=0;
1937         USER_TRANS[015]=0;
1938         USER_TRANS[033]=0;
1939         return 0;
1940 }
1941 
1942 int con_get_trans(char * arg)
     /* [previous][next][first][last][top][bottom][index][help] */
1943 {
1944         int i;
1945 
1946         i = verify_area(VERIFY_WRITE, (void *)arg, E_TABSZ);
1947         if (i)
1948                 return i;
1949 
1950         for (i=0; i<E_TABSZ ; i++) put_fs_byte(USER_TRANS[i],arg+i);
1951         return 0;
1952 }

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