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

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