root/kernel/chr_drv/console.c

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

DEFINITIONS

This source file includes following definitions.
  1. gotoxy
  2. set_origin
  3. scrup
  4. scrdown
  5. lf
  6. ri
  7. cr
  8. bs
  9. del
  10. csi_J
  11. csi_K
  12. update_attr
  13. default_attr
  14. csi_m
  15. hide_cursor
  16. set_cursor
  17. respond_string
  18. respond_num
  19. cursor_report
  20. status_report
  21. respond_ID
  22. invert_screen
  23. set_mode
  24. setterm_command
  25. insert_char
  26. insert_line
  27. delete_char
  28. delete_line
  29. csi_at
  30. csi_L
  31. csi_P
  32. csi_M
  33. save_cur
  34. restore_cur
  35. reset_terminal
  36. con_write
  37. do_keyboard_interrupt
  38. memsetw
  39. con_init
  40. kbdsave
  41. get_scrmem
  42. set_scrmem
  43. blank_screen
  44. unblank_screen
  45. update_screen
  46. sysbeepstop
  47. sysbeep
  48. do_screendump
  49. console_print
  50. con_open

   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  *      'void con_open(struct tty_queue * queue, struct )'
  14  *      'void update_screen(int new_console)'
  15  *      'void blank_screen(void)'
  16  *      'void unblank_screen(void)'
  17  * 
  18  * Hopefully this will be a rather complete VT102 implementation.
  19  *
  20  * Beeping thanks to John T Kohl.
  21  * 
  22  * Virtual Consoles, Screen Blanking, Screen Dumping, Color, Graphics
  23  *   Chars, and VT100 enhancements by Peter MacDonald.
  24  */
  25 
  26 /*
  27  *  NOTE!!! We sometimes disable and enable interrupts for a short while
  28  * (to put a word in video IO), but this will work even for keyboard
  29  * interrupts. We know interrupts aren't enabled when getting a keyboard
  30  * interrupt, as we use trap-gates. Hopefully all is well.
  31  */
  32 
  33 /*
  34  * Code to check for different video-cards mostly by Galen Hunt,
  35  * <g-hunt@ee.utah.edu>
  36  */
  37 
  38 #define KEYBOARD_IRQ 1
  39 
  40 #include <linux/sched.h>
  41 #include <linux/timer.h>
  42 #include <linux/tty.h>
  43 #include <linux/config.h>
  44 #include <linux/kernel.h>
  45 #include <linux/string.h>
  46 #include <linux/errno.h>
  47 #include <linux/kd.h>
  48 
  49 #include <asm/io.h>
  50 #include <asm/system.h>
  51 #include <asm/segment.h>
  52 
  53 #include "vt_kern.h"
  54 
  55 #define NPAR 16
  56 
  57 extern void vt_init(void);
  58 extern void keyboard_interrupt(int pt_regs);
  59 extern void set_leds(void);
  60 extern unsigned char kapplic;
  61 extern unsigned char ckmode;
  62 extern unsigned char krepeat;
  63 extern unsigned char default_kleds;
  64 extern unsigned char kleds;
  65 extern unsigned char kmode;
  66 extern unsigned char kraw;
  67 extern unsigned char ke0;
  68 extern unsigned char lfnlmode;
  69 
  70 unsigned long   video_num_columns;              /* Number of text columns       */
  71 unsigned long   video_num_lines;                /* Number of test lines         */
  72 
  73 static unsigned char    video_type;             /* Type of display being used   */
  74 static unsigned long    video_mem_base;         /* Base of video memory         */
  75 static unsigned long    video_mem_term;         /* End of video memory          */
  76 static unsigned long    video_size_row;         /* Bytes per row                */
  77 static unsigned char    video_page;             /* Initial video page           */
  78 static unsigned short   video_port_reg;         /* Video register select port   */
  79 static unsigned short   video_port_val;         /* Video register value port    */
  80 static int can_do_color = 0;
  81 
  82 static struct {
  83         unsigned short  vc_video_erase_char;    /* Background erase character */
  84         unsigned char   vc_attr;                /* Current attributes */
  85         unsigned char   vc_def_color;           /* Default colors */
  86         unsigned char   vc_color;               /* Foreground & background */
  87         unsigned char   vc_s_color;             /* Saved foreground & background */
  88         unsigned char   vc_ulcolor;             /* Colour for underline mode */
  89         unsigned char   vc_halfcolor;           /* Colour for half intensity mode */
  90         unsigned long   vc_origin;              /* Used for EGA/VGA fast scroll */
  91         unsigned long   vc_scr_end;             /* Used for EGA/VGA fast scroll */
  92         unsigned long   vc_pos;
  93         unsigned long   vc_x,vc_y;
  94         unsigned long   vc_top,vc_bottom;
  95         unsigned long   vc_state;
  96         unsigned long   vc_npar,vc_par[NPAR];
  97         unsigned long   vc_video_mem_start;     /* Start of video RAM           */
  98         unsigned long   vc_video_mem_end;       /* End of video RAM (sort of)   */
  99         unsigned long   vc_saved_x;
 100         unsigned long   vc_saved_y;
 101         /* mode flags */
 102         unsigned long   vc_kbdapplic    : 1;    /* Application keyboard */
 103         unsigned long   vc_charset      : 1;    /* Character set G0 / G1 */
 104         unsigned long   vc_s_charset    : 1;    /* Saved character set */
 105         unsigned long   vc_decckm       : 1;    /* Cursor Keys Mode */
 106         unsigned long   vc_decscnm      : 1;    /* Screen Mode */
 107         unsigned long   vc_decom        : 1;    /* Origin Mode */
 108         unsigned long   vc_decawm       : 1;    /* Autowrap Mode */
 109         unsigned long   vc_decarm       : 1;    /* Autorepeat Mode */
 110         unsigned long   vc_deccm        : 1;    /* Cursor Visible */
 111         unsigned long   vc_decim        : 1;    /* Insert Mode */
 112         unsigned long   vc_lnm          : 1;    /* Line feed New line Mode */
 113         /* attribute flags */
 114         unsigned long   vc_intensity    : 2;    /* 0=half-bright, 1=normal, 2=bold */
 115         unsigned long   vc_underline    : 1;
 116         unsigned long   vc_blink        : 1;
 117         unsigned long   vc_reverse      : 1;
 118         unsigned long   vc_s_intensity  : 2;    /* saved rendition */
 119         unsigned long   vc_s_underline  : 1;
 120         unsigned long   vc_s_blink      : 1;
 121         unsigned long   vc_s_reverse    : 1;
 122         /* misc */
 123         unsigned long   vc_ques         : 1;
 124         unsigned long   vc_need_wrap    : 1;
 125         unsigned long   vc_tab_stop[5];         /* Tab stops. 160 columns. */
 126         unsigned char   vc_kbdmode;
 127         char *          vc_translate;
 128         char *          vc_G0_charset;
 129         char *          vc_G1_charset;
 130         char *          vc_saved_G0;
 131         char *          vc_saved_G1;
 132         /* additional information is in vt_kern.h */
 133 } vc_cons [NR_CONSOLES];
 134 
 135 #define MEM_BUFFER_SIZE (2*80*50*8) 
 136 
 137 unsigned short *vc_scrbuf[NR_CONSOLES];
 138 static unsigned short * vc_scrmembuf;
 139 static int console_blanked = 0;
 140 
 141 #define origin          (vc_cons[currcons].vc_origin)
 142 #define scr_end         (vc_cons[currcons].vc_scr_end)
 143 #define pos             (vc_cons[currcons].vc_pos)
 144 #define top             (vc_cons[currcons].vc_top)
 145 #define bottom          (vc_cons[currcons].vc_bottom)
 146 #define x               (vc_cons[currcons].vc_x)
 147 #define y               (vc_cons[currcons].vc_y)
 148 #define state           (vc_cons[currcons].vc_state)
 149 #define npar            (vc_cons[currcons].vc_npar)
 150 #define par             (vc_cons[currcons].vc_par)
 151 #define ques            (vc_cons[currcons].vc_ques)
 152 #define attr            (vc_cons[currcons].vc_attr)
 153 #define saved_x         (vc_cons[currcons].vc_saved_x)
 154 #define saved_y         (vc_cons[currcons].vc_saved_y)
 155 #define translate       (vc_cons[currcons].vc_translate)
 156 #define G0_charset      (vc_cons[currcons].vc_G0_charset)
 157 #define G1_charset      (vc_cons[currcons].vc_G1_charset)
 158 #define saved_G0        (vc_cons[currcons].vc_saved_G0)
 159 #define saved_G1        (vc_cons[currcons].vc_saved_G1)
 160 #define video_mem_start (vc_cons[currcons].vc_video_mem_start)
 161 #define video_mem_end   (vc_cons[currcons].vc_video_mem_end)
 162 #define video_erase_char (vc_cons[currcons].vc_video_erase_char)        
 163 #define decckm          (vc_cons[currcons].vc_decckm)
 164 #define decscnm         (vc_cons[currcons].vc_decscnm)
 165 #define decom           (vc_cons[currcons].vc_decom)
 166 #define decawm          (vc_cons[currcons].vc_decawm)
 167 #define decarm          (vc_cons[currcons].vc_decarm)
 168 #define deccm           (vc_cons[currcons].vc_deccm)
 169 #define decim           (vc_cons[currcons].vc_decim)
 170 #define lnm             (vc_cons[currcons].vc_lnm)
 171 #define kbdapplic       (vc_cons[currcons].vc_kbdapplic)
 172 #define need_wrap       (vc_cons[currcons].vc_need_wrap)
 173 #define color           (vc_cons[currcons].vc_color)
 174 #define s_color         (vc_cons[currcons].vc_s_color)
 175 #define def_color       (vc_cons[currcons].vc_def_color)
 176 #define foreground      (color & 0x0f)
 177 #define background      (color & 0xf0)
 178 #define charset         (vc_cons[currcons].vc_charset)
 179 #define s_charset       (vc_cons[currcons].vc_s_charset)
 180 #define intensity       (vc_cons[currcons].vc_intensity)
 181 #define underline       (vc_cons[currcons].vc_underline)
 182 #define blink           (vc_cons[currcons].vc_blink)
 183 #define reverse         (vc_cons[currcons].vc_reverse)
 184 #define s_intensity     (vc_cons[currcons].vc_s_intensity)
 185 #define s_underline     (vc_cons[currcons].vc_s_underline)
 186 #define s_blink         (vc_cons[currcons].vc_s_blink)
 187 #define s_reverse       (vc_cons[currcons].vc_s_reverse)
 188 #define ulcolor         (vc_cons[currcons].vc_ulcolor)
 189 #define halfcolor       (vc_cons[currcons].vc_halfcolor)
 190 #define kbdmode         (vc_cons[currcons].vc_kbdmode)
 191 #define tab_stop        (vc_cons[currcons].vc_tab_stop)
 192 #define kbdraw          (vt_cons[currcons].vc_kbdraw)
 193 #define kbdleds         (vt_cons[currcons].vc_kbdleds)
 194 #define vtmode          (vt_cons[currcons].vt_mode)
 195 
 196 #define SET(mode,fg,v) \
 197         (mode) = (v); \
 198         if (currcons == fg_console) \
 199                 (fg) = (v)
 200 
 201 int blankinterval = 10*60*HZ;
 202 static int screen_size = 0;
 203 
 204 static void sysbeep(void);
 205 
 206 /*
 207  * this is what the terminal answers to a ESC-Z or csi0c query.
 208  */
 209 #define VT100ID "\033[?1;2c"
 210 #define VT102ID "\033[?6c"
 211 
 212 static char * translations[] = {
 213 /* 8-bit Latin-1 mapped to the PC charater set: '\0' means non-printable */
 214         "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
 215         "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
 216         " !\"#$%&'()*+,-./0123456789:;<=>?"
 217         "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
 218         "`abcdefghijklmnopqrstuvwxyz{|}~\0"
 219         "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
 220         "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
 221         "\040\255\233\234\376\235\174\025\376\376\246\256\252\055\376\376"
 222         "\370\361\375\376\376\346\024\371\376\376\247\257\254\253\376\250"
 223         "\376\376\376\376\216\217\222\200\376\220\376\376\376\376\376\376"
 224         "\376\245\376\376\376\376\231\376\376\376\376\376\232\376\376\341"
 225         "\205\240\203\376\204\206\221\207\212\202\210\211\215\241\214\213"
 226         "\376\244\225\242\223\376\224\366\376\227\243\226\201\376\376\230",
 227 /* vt100 graphics */
 228         "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
 229         "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
 230         " !\"#$%&'()*+,-./0123456789:;<=>?"
 231         "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^ "
 232         "\004\261\007\007\007\007\370\361\040\007\331\277\332\300\305\007"
 233         "\007\304\007\007\303\264\301\302\263\007\007\007\007\007\234\0"
 234         "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
 235         "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
 236         "\040\255\233\234\376\235\174\025\376\376\246\256\252\055\376\376"
 237         "\370\361\375\376\376\346\024\371\376\376\247\257\254\253\376\250"
 238         "\376\376\376\376\216\217\222\200\376\220\376\376\376\376\376\376"
 239         "\376\245\376\376\376\376\231\376\376\376\376\376\232\376\376\341"
 240         "\205\240\203\376\204\206\221\207\212\202\210\211\215\241\214\213"
 241         "\376\244\225\242\223\376\224\366\376\227\243\226\201\376\376\230",
 242 /* IBM grapgics: minimal translations (CR, LF, LL and ESC) */
 243         "\000\001\002\003\004\005\006\007\010\011\000\013\000\000\016\017"
 244         "\020\021\022\023\024\025\026\027\030\031\032\000\034\035\036\037"
 245         "\040\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057"
 246         "\060\061\062\063\064\065\066\067\070\071\072\073\074\075\076\077"
 247         "\100\101\102\103\104\105\106\107\110\111\112\113\114\115\116\117"
 248         "\120\121\122\123\124\125\126\127\130\131\132\133\134\135\136\137"
 249         "\140\141\142\143\144\145\146\147\150\151\152\153\154\155\156\157"
 250         "\160\161\162\163\164\165\166\167\170\171\172\173\174\175\176\177"
 251         "\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217"
 252         "\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237"
 253         "\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257"
 254         "\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277"
 255         "\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317"
 256         "\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337"
 257         "\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357"
 258         "\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377"
 259 };
 260 
 261 #define NORM_TRANS (translations[0])
 262 #define GRAF_TRANS (translations[1])
 263 #define NULL_TRANS (translations[2])
 264 
 265 static unsigned char color_table[] = { 0, 4, 2, 6, 1, 5, 3, 7,
 266                                        8,12,10,14, 9,13,11,15 };
 267 
 268 /*
 269  * gotoxy() must verify all boundaries, because the arguments
 270  * might also be negative. If the given position is out of
 271  * bounds, the cursor is placed at the nearest margin.
 272  */
 273 static void gotoxy(int currcons, int new_x, int new_y)
     /* [previous][next][first][last][top][bottom][index][help] */
 274 {
 275         int max_y;
 276 
 277         if (new_x < 0)
 278                 x = 0;
 279         else
 280                 if (new_x >= video_num_columns)
 281                         x = video_num_columns - 1;
 282                 else
 283                         x = new_x;
 284         if (decom) {
 285                 new_y += top;
 286                 max_y = bottom;
 287         } else
 288                 max_y = video_num_lines;
 289         if (new_y < 0)
 290                 y = 0;
 291         else
 292                 if (new_y >= max_y)
 293                         y = max_y - 1;
 294                 else
 295                         y = new_y;
 296         pos = origin + y*video_size_row + (x<<1);
 297         need_wrap = 0;
 298 }
 299 
 300 static void set_origin(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 301 {
 302         if (video_type != VIDEO_TYPE_EGAC && video_type != VIDEO_TYPE_EGAM)
 303                 return;
 304         if (currcons != fg_console || console_blanked || vtmode == KD_GRAPHICS)
 305                 return;
 306         cli();
 307         outb_p(12, video_port_reg);
 308         outb_p(0xff&((origin-video_mem_base)>>9), video_port_val);
 309         outb_p(13, video_port_reg);
 310         outb_p(0xff&((origin-video_mem_base)>>1), video_port_val);
 311         sti();
 312 }
 313 
 314 static void scrup(int currcons, unsigned int t, unsigned int b)
     /* [previous][next][first][last][top][bottom][index][help] */
 315 {
 316         int hardscroll = 1;
 317 
 318         if (b > video_num_lines || t >= b)
 319                 return;
 320         if (video_type != VIDEO_TYPE_EGAC && video_type != VIDEO_TYPE_EGAM)
 321                 hardscroll = 0;
 322         else if (t || b != video_num_lines)
 323                 hardscroll = 0;
 324         if (hardscroll) {
 325                 origin += video_size_row;
 326                 pos += video_size_row;
 327                 scr_end += video_size_row;
 328                 if (scr_end > video_mem_end) {
 329                         __asm__("cld\n\t"
 330                                 "rep\n\t"
 331                                 "movsl\n\t"
 332                                 "movl _video_num_columns,%1\n\t"
 333                                 "rep\n\t"
 334                                 "stosw"
 335                                 ::"a" (video_erase_char),
 336                                 "c" ((video_num_lines-1)*video_num_columns>>1),
 337                                 "D" (video_mem_start),
 338                                 "S" (origin)
 339                                 :"cx","di","si");
 340                         scr_end -= origin-video_mem_start;
 341                         pos -= origin-video_mem_start;
 342                         origin = video_mem_start;
 343                 } else {
 344                         __asm__("cld\n\t"
 345                                 "rep\n\t"
 346                                 "stosw"
 347                                 ::"a" (video_erase_char),
 348                                 "c" (video_num_columns),
 349                                 "D" (scr_end-video_size_row)
 350                                 :"cx","di");
 351                 }
 352                 set_origin(currcons);
 353         } else {
 354                 __asm__("cld\n\t"
 355                         "rep\n\t"
 356                         "movsl\n\t"
 357                         "movl _video_num_columns,%%ecx\n\t"
 358                         "rep\n\t"
 359                         "stosw"
 360                         ::"a" (video_erase_char),
 361                         "c" ((b-t-1)*video_num_columns>>1),
 362                         "D" (origin+video_size_row*t),
 363                         "S" (origin+video_size_row*(t+1))
 364                         :"cx","di","si");
 365         }
 366 }
 367 
 368 static void scrdown(int currcons, unsigned int t, unsigned int b)
     /* [previous][next][first][last][top][bottom][index][help] */
 369 {
 370         if (b > video_num_lines || t >= b)
 371                 return;
 372         __asm__("std\n\t"
 373                 "rep\n\t"
 374                 "movsl\n\t"
 375                 "addl $2,%%edi\n\t"     /* %edi has been decremented by 4 */
 376                 "movl _video_num_columns,%%ecx\n\t"
 377                 "rep\n\t"
 378                 "stosw\n\t"
 379                 "cld"
 380                 ::"a" (video_erase_char),
 381                 "c" ((b-t-1)*video_num_columns>>1),
 382                 "D" (origin+video_size_row*b-4),
 383                 "S" (origin+video_size_row*(b-1)-4)
 384                 :"ax","cx","di","si");
 385 }
 386 
 387 static void lf(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 388 {
 389         if (y+1<bottom) {
 390                 y++;
 391                 pos += video_size_row;
 392                 return;
 393         } else 
 394                 scrup(currcons,top,bottom);
 395         need_wrap = 0;
 396 }
 397 
 398 static void ri(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 399 {
 400         if (y>top) {
 401                 y--;
 402                 pos -= video_size_row;
 403                 return;
 404         } else
 405                 scrdown(currcons,top,bottom);
 406         need_wrap = 0;
 407 }
 408 
 409 static inline void cr(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 410 {
 411         pos -= x<<1;
 412         need_wrap = x = 0;
 413 }
 414 
 415 static inline void bs(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 416 {
 417         if (x) {
 418                 pos -= 2;
 419                 x--;
 420                 need_wrap = 0;
 421         }
 422 }
 423 
 424 static inline void del(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 425 {
 426         if (x) {
 427                 pos -= 2;
 428                 x--;
 429                 *(unsigned short *)pos = video_erase_char;
 430                 need_wrap = 0;
 431         }
 432 }
 433 
 434 static void csi_J(int currcons, int vpar)
     /* [previous][next][first][last][top][bottom][index][help] */
 435 {
 436         unsigned long count;
 437         unsigned long start;
 438 
 439         switch (vpar) {
 440                 case 0: /* erase from cursor to end of display */
 441                         count = (scr_end-pos)>>1;
 442                         start = pos;
 443                         break;
 444                 case 1: /* erase from start to cursor */
 445                         count = ((pos-origin)>>1)+1;
 446                         start = origin;
 447                         break;
 448                 case 2: /* erase whole display */
 449                         count = video_num_columns * video_num_lines;
 450                         start = origin;
 451                         break;
 452                 default:
 453                         return;
 454         }
 455         __asm__("cld\n\t"
 456                 "rep\n\t"
 457                 "stosw\n\t"
 458                 ::"c" (count),
 459                 "D" (start),"a" (video_erase_char)
 460                 :"cx","di");
 461         need_wrap = 0;
 462 }
 463 
 464 static void csi_K(int currcons, int vpar)
     /* [previous][next][first][last][top][bottom][index][help] */
 465 {
 466         long count;
 467         long start;
 468 
 469         switch (vpar) {
 470                 case 0: /* erase from cursor to end of line */
 471                         count = video_num_columns-x;
 472                         start = pos;
 473                         break;
 474                 case 1: /* erase from start of line to cursor */
 475                         start = pos - (x<<1);
 476                         count = x+1;
 477                         break;
 478                 case 2: /* erase whole line */
 479                         start = pos - (x<<1);
 480                         count = video_num_columns;
 481                         break;
 482                 default:
 483                         return;
 484         }
 485         __asm__("cld\n\t"
 486                 "rep\n\t"
 487                 "stosw\n\t"
 488                 ::"c" (count),
 489                 "D" (start),"a" (video_erase_char)
 490                 :"cx","di");
 491         need_wrap = 0;
 492 }
 493 
 494 /*
 495  *  I hope this works. The monochrome part is untested.
 496  */
 497 static void update_attr(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 498 {
 499         attr = color;
 500         if (can_do_color) {
 501                 if (underline)
 502                         attr = (attr & 0xf0) | ulcolor;
 503                 else if (intensity == 0)
 504                         attr = (attr & 0xf0) | halfcolor;
 505         }
 506         if (reverse ^ decscnm)
 507                 attr = (attr & 0x88) | (((attr >> 4) | (attr << 4)) & 0x77);
 508         if (blink)
 509                 attr ^= 0x80;
 510         if (intensity == 2)
 511                 attr ^= 0x08;
 512         if (!can_do_color) {
 513                 if (underline)
 514                         attr = (attr & 0xf8) | 0x01;
 515                 else if (intensity == 0)
 516                         attr = (attr & 0xf0) | 0x08;
 517         }
 518         if (decscnm)
 519                 video_erase_char = ((color & 0x88) | (((color >> 4) |
 520                         (color << 4)) & 0x77) << 8) | ' ';
 521         else
 522                 video_erase_char = (color << 8) | ' ';
 523 }
 524 
 525 static void default_attr(int currcons) {
     /* [previous][next][first][last][top][bottom][index][help] */
 526         intensity = 1;
 527         underline = 0;
 528         reverse = 0;
 529         blink = 0;
 530         color = def_color;
 531 }
 532 
 533 static void csi_m(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 534 {
 535         int i;
 536 
 537         for (i=0;i<=npar;i++)
 538                 switch (par[i]) {
 539                         case 0: /* all attributes off */
 540                                 default_attr(currcons);
 541                                 break;
 542                         case 1:
 543                                 intensity = 2;
 544                                 break;
 545                         case 2:
 546                                 intensity = 0;
 547                                 break;
 548                         case 4:
 549                                 underline = 1;
 550                                 break;
 551                         case 5:
 552                                 blink = 1;
 553                                 break;
 554                         case 7:
 555                                 reverse = 1;
 556                                 break;
 557                         case 21:
 558                         case 22:
 559                                 intensity = 1;
 560                                 break;
 561                         case 24:
 562                                 underline = 0;
 563                                 break;
 564                         case 25:
 565                                 blink = 0;
 566                                 break;
 567                         case 27:
 568                                 reverse = 0;
 569                                 break;
 570                         case 39:
 571                                 color = (def_color & 0x0f) | background;
 572                                 break;
 573                         case 49:
 574                                 color = (def_color & 0xf0) | foreground;
 575                                 break;
 576                         default:
 577                                 if (par[i] >= 30 && par[i] <= 37)
 578                                         color = color_table[par[i]-30]
 579                                                 | background; 
 580                                 else if (par[i] >= 40 && par[i] <= 47)
 581                                         color = (color_table[par[i]-40]<<4)
 582                                                 | foreground;
 583                                 break;
 584                 }
 585         update_attr(currcons);
 586 }
 587 
 588 static inline void hide_cursor(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 589 {
 590         outb_p(14, video_port_reg);
 591         outb_p(0xff&((scr_end-video_mem_base)>>9), video_port_val);
 592         outb_p(15, video_port_reg);
 593         outb_p(0xff&((scr_end-video_mem_base)>>1), video_port_val);
 594 }
 595 
 596 static inline void set_cursor(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 597 {
 598         if (currcons != fg_console || console_blanked)
 599                 return;
 600         cli();
 601         if (deccm) {
 602                 outb_p(14, video_port_reg);
 603                 outb_p(0xff&((pos-video_mem_base)>>9), video_port_val);
 604                 outb_p(15, video_port_reg);
 605                 outb_p(0xff&((pos-video_mem_base)>>1), video_port_val);
 606         } else
 607                 hide_cursor(currcons);
 608         sti();
 609 }
 610 
 611 static void respond_string(char * p, int currcons, struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 612 {
 613         while (*p) {
 614                 put_tty_queue(*p, &tty->read_q);
 615                 p++;
 616         }
 617         TTY_READ_FLUSH(tty);
 618 }
 619 
 620 static void respond_num(unsigned int n, int currcons, struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 621 {
 622         char buff[3];
 623         int i = 0;
 624 
 625         do {
 626                 buff[i++] = (n%10)+'0';
 627                 n /= 10;
 628         } while(n && i < 3);    /* We'll take no chances */
 629         while (i--) {
 630                 put_tty_queue(buff[i], &tty->read_q);
 631         }
 632         /* caller must flush */
 633 }
 634 
 635 static void cursor_report(int currcons, struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 636 {
 637         put_tty_queue('\033', &tty->read_q);
 638         put_tty_queue('[', &tty->read_q);
 639         respond_num(y + (decom ? top+1 : 1), currcons, tty);
 640         put_tty_queue(';', &tty->read_q);
 641         respond_num(x+1, currcons, tty);
 642         put_tty_queue('R', &tty->read_q);
 643         TTY_READ_FLUSH(tty);
 644 }
 645 
 646 static inline void status_report(int currcons, struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 647 {
 648         respond_string("\033[0n", currcons, tty);       /* Terminal ok */
 649 }
 650 
 651 static inline void respond_ID(int currcons, struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 652 {
 653         respond_string(VT102ID, currcons, tty);
 654 }
 655 
 656 static void invert_screen(int currcons) {
     /* [previous][next][first][last][top][bottom][index][help] */
 657         unsigned char *p;
 658 
 659         if (can_do_color)
 660                 for (p = (unsigned char *)origin+1; p < (unsigned char *)scr_end; p+=2)
 661                         *p = (*p & 0x88) | (((*p >> 4) | (*p << 4)) & 0x77);
 662         else
 663                 for (p = (unsigned char *)origin+1; p < (unsigned char *)scr_end; p+=2)
 664                         *p ^= *p & 0x07 == 1 ? 0x70 : 0x77;
 665 }
 666 
 667 static void set_mode(int currcons, int on_off)
     /* [previous][next][first][last][top][bottom][index][help] */
 668 {
 669         int i;
 670 
 671         for (i=0; i<=npar; i++)
 672                 if (ques) switch(par[i]) {      /* DEC private modes set/reset */
 673                         case 1:                 /* Cursor keys send ^[Ox/^[[x */
 674                                 SET(decckm,ckmode,on_off);
 675                                 break;
 676                         case 3: /* 80/132 mode switch unimplemented */
 677                                 csi_J(currcons,2);
 678                                 gotoxy(currcons,0,0);
 679                                 break;
 680                         case 5:                 /* Inverted screen on/off */
 681                                 if (decscnm != on_off) {
 682                                         decscnm = on_off;
 683                                         invert_screen(currcons);
 684                                         update_attr(currcons);
 685                                 }
 686                                 break;
 687                         case 6:                 /* Origin relative/absolute */
 688                                 decom = on_off;
 689                                 gotoxy(currcons,0,0);
 690                                 break;
 691                         case 7:                 /* Autowrap on/off */
 692                                 decawm = on_off;
 693                                 break;
 694                         case 8:                 /* Autorepeat on/off */
 695                                 SET(decarm,krepeat,on_off);
 696                                 break;
 697                         case 25:                /* Cursor on/off */
 698                                 deccm = on_off;
 699                                 set_cursor(currcons);
 700                                 break;
 701                 } else switch(par[i]) {         /* ANSI modes set/reset */
 702                         case 4:                 /* Insert Mode on/off */
 703                                 decim = on_off;
 704                                 break;
 705                         case 20:                /* Lf, Enter == CrLf/Lf */
 706                                 SET(lnm,lfnlmode,on_off);
 707                                 break;
 708                 }
 709 }
 710 
 711 static void setterm_command(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 712 {
 713         switch(par[0]) {
 714                 case 1: /* set color for underline mode */
 715                         if (can_do_color && par[1] < 16) {
 716                                 ulcolor = color_table[par[1]];
 717                                 if (underline)
 718                                         update_attr(currcons);
 719                         }
 720                         break;
 721                 case 2: /* set color for half intensity mode */
 722                         if (can_do_color && par[1] < 16) {
 723                                 halfcolor = color_table[par[1]];
 724                                 if (intensity == 0)
 725                                         update_attr(currcons);
 726                         }
 727                         break;
 728                 case 8: /* store colors as defaults */
 729                         def_color = attr;
 730                         default_attr(currcons);
 731                         update_attr(currcons);
 732                         break;
 733                 case 9: /* set blanking interval */
 734                         blankinterval = ((par[1] < 60) ? par[1] : 60) * 60 * HZ;
 735                         break;
 736         }
 737 }
 738 
 739 static void insert_char(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 740 {
 741         unsigned int i = x;
 742         unsigned short tmp, old = video_erase_char;
 743         unsigned short * p = (unsigned short *) pos;
 744 
 745         while (i++ < video_num_columns) {
 746                 tmp = *p;
 747                 *p = old;
 748                 old = tmp;
 749                 p++;
 750         }
 751         need_wrap = 0;
 752 }
 753 
 754 static void insert_line(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 755 {
 756         scrdown(currcons,y,bottom);
 757         need_wrap = 0;
 758 }
 759 
 760 static void delete_char(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 761 {
 762         unsigned int i = x;
 763         unsigned short * p = (unsigned short *) pos;
 764 
 765         while (++i < video_num_columns) {
 766                 *p = *(p+1);
 767                 p++;
 768         }
 769         *p = video_erase_char;
 770         need_wrap = 0;
 771 }
 772 
 773 static void delete_line(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 774 {
 775         scrup(currcons,y,bottom);
 776         need_wrap = 0;
 777 }
 778 
 779 static void csi_at(int currcons, unsigned int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
 780 {
 781         if (nr > video_num_columns)
 782                 nr = video_num_columns;
 783         else if (!nr)
 784                 nr = 1;
 785         while (nr--)
 786                 insert_char(currcons);
 787 }
 788 
 789 static void csi_L(int currcons, unsigned int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
 790 {
 791         if (nr > video_num_lines)
 792                 nr = video_num_lines;
 793         else if (!nr)
 794                 nr = 1;
 795         while (nr--)
 796                 insert_line(currcons);
 797 }
 798 
 799 static void csi_P(int currcons, unsigned int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
 800 {
 801         if (nr > video_num_columns)
 802                 nr = video_num_columns;
 803         else if (!nr)
 804                 nr = 1;
 805         while (nr--)
 806                 delete_char(currcons);
 807 }
 808 
 809 static void csi_M(int currcons, unsigned int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
 810 {
 811         if (nr > video_num_lines)
 812                 nr = video_num_lines;
 813         else if (!nr)
 814                 nr=1;
 815         while (nr--)
 816                 delete_line(currcons);
 817 }
 818 
 819 static void save_cur(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 820 {
 821         saved_x         = x;
 822         saved_y         = y;
 823         s_intensity     = intensity;
 824         s_underline     = underline;
 825         s_blink         = blink;
 826         s_reverse       = reverse;
 827         s_charset       = charset;
 828         s_color         = color;
 829         saved_G0        = G0_charset;
 830         saved_G1        = G1_charset;
 831 }
 832 
 833 static void restore_cur(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 834 {
 835         gotoxy(currcons,saved_x,saved_y);
 836         intensity       = s_intensity;
 837         underline       = s_underline;
 838         blink           = s_blink;
 839         reverse         = s_reverse;
 840         charset         = s_charset;
 841         color           = s_color;
 842         G0_charset      = saved_G0;
 843         G1_charset      = saved_G1;
 844         translate       = charset ? G1_charset : G0_charset;
 845         update_attr(currcons);
 846         need_wrap = 0;
 847 }
 848 
 849 enum { ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey, 
 850         EShash, ESsetG0, ESsetG1, ESignore };
 851 
 852 static void reset_terminal(int currcons, int do_clear)
     /* [previous][next][first][last][top][bottom][index][help] */
 853 {
 854         top             = 0;
 855         bottom          = video_num_lines;
 856         state           = ESnormal;
 857         ques            = 0;
 858         translate       = NORM_TRANS;
 859         G0_charset      = NORM_TRANS;
 860         G1_charset      = GRAF_TRANS;
 861         charset         = 0;
 862         need_wrap       = 0;
 863 
 864         decscnm         = 0;
 865         decom           = 0;
 866         decawm          = 1;
 867         deccm           = 1;
 868         decim           = 0;
 869 
 870         if (currcons == fg_console) {
 871                 krepeat         = 1;
 872                 ckmode          = 0;
 873                 kapplic         = 0;
 874                 lfnlmode        = 0;
 875                 kleds           = default_kleds;
 876                 kmode           = 0;
 877                 set_leds();
 878         } else {
 879                 decarm          = 1;
 880                 decckm          = 0;
 881                 kbdapplic       = 0;
 882                 lnm             = 0;
 883                 kbdleds         = default_kleds;
 884                 kbdmode         = 0;
 885         }
 886 
 887         default_attr(currcons);
 888         update_attr(currcons);
 889 
 890         tab_stop[0]     = 0x01010100;
 891         tab_stop[1]     =
 892         tab_stop[2]     =
 893         tab_stop[3]     =
 894         tab_stop[4]     = 0x01010101;
 895 
 896         if (do_clear) {
 897                 gotoxy(currcons,0,0);
 898                 csi_J(currcons,2);
 899                 save_cur(currcons);
 900         }
 901 }
 902 
 903 void con_write(struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 904 {
 905         int c;
 906         unsigned int currcons;
 907 
 908         wake_up(&tty->write_q.proc_list);
 909         currcons = tty->line - 1;
 910         if (currcons >= NR_CONSOLES) {
 911                 printk("con_write: illegal tty (%d)\n", currcons);
 912                 return;
 913         }
 914         while (!tty->stopped && (c = get_tty_queue(&tty->write_q)) >= 0) {
 915                 if (state == ESnormal && translate[c]) {
 916                         if (need_wrap) {
 917                                 cr(currcons);
 918                                 lf(currcons);
 919                         }
 920                         if (decim)
 921                                 insert_char(currcons);
 922                         c = translate[c];
 923                         *(char *) pos = c;
 924                         *(char *) (pos+1) = attr;
 925                         if (x == video_num_columns - 1)
 926                                 need_wrap = decawm;
 927                         else {
 928                                 x++;
 929                                 pos+=2;
 930                         }
 931                         continue;
 932                 }
 933 
 934                 /*
 935                  *  Control characters can be used in the _middle_
 936                  *  of an escape sequence.
 937                  */
 938                 switch (c) {
 939                         case 7:
 940                                 sysbeep();
 941                                 continue;
 942                         case 8:
 943                                 bs(currcons);
 944                                 continue;
 945                         case 9:
 946                                 pos -= (x << 1);
 947                                 while (x < video_num_columns - 1) {
 948                                         x++;
 949                                         if (tab_stop[x >> 5] & (1 << (x & 31)))
 950                                                 break;
 951                                 }
 952                                 pos += (x << 1);
 953                                 continue;
 954                         case 10: case 11: case 12:
 955                                 lf(currcons);
 956                                 if (!lfnlmode)
 957                                         continue;
 958                         case 13:
 959                                 cr(currcons);
 960                                 continue;
 961                         case 14:
 962                                 charset = 1;
 963                                 translate = G1_charset;
 964                                 continue;
 965                         case 15:
 966                                 charset = 0;
 967                                 translate = G0_charset;
 968                                 continue;
 969                         case 24: case 26:
 970                                 state = ESnormal;
 971                                 continue;
 972                         case 27:
 973                                 state = ESesc;
 974                                 continue;
 975                         case 127:
 976                                 del(currcons);
 977                                 continue;
 978                         case 128+27:
 979                                 state = ESsquare;
 980                                 continue;
 981                 }
 982                 switch(state) {
 983                         case ESesc:
 984                                 state = ESnormal;
 985                                 switch (c) {
 986                                   case '[':
 987                                         state = ESsquare;
 988                                         continue;
 989                                   case 'E':
 990                                         cr(currcons);
 991                                         lf(currcons);
 992                                         continue;
 993                                   case 'M':
 994                                         ri(currcons);
 995                                         continue;
 996                                   case 'D':
 997                                         lf(currcons);
 998                                         continue;
 999                                   case 'H':
1000                                         tab_stop[x >> 5] |= (1 << (x & 31));
1001                                         continue;
1002                                   case 'Z':
1003                                         respond_ID(currcons,tty);
1004                                         continue;
1005                                   case '7':
1006                                         save_cur(currcons);
1007                                         continue;
1008                                   case '8':
1009                                         restore_cur(currcons);
1010                                         continue;
1011                                   case '(':
1012                                         state = ESsetG0;
1013                                         continue;
1014                                   case ')':
1015                                         state = ESsetG1;
1016                                         continue;
1017                                   case '#':
1018                                         state = EShash;
1019                                         continue;
1020                                   case 'c':
1021                                         reset_terminal(currcons,1);
1022                                         continue;
1023                                   case '>':  /* Numeric keypad */
1024                                         SET(kbdapplic,kapplic,0);
1025                                         continue;
1026                                   case '=':  /* Appl. keypad */
1027                                         SET(kbdapplic,kapplic,1);
1028                                         continue;
1029                                 }       
1030                                 continue;
1031                         case ESsquare:
1032                                 for(npar = 0 ; npar < NPAR ; npar++)
1033                                         par[npar] = 0;
1034                                 npar = 0;
1035                                 state = ESgetpars;
1036                                 if (c == '[') { /* Function key */
1037                                         state=ESfunckey;
1038                                         continue;
1039                                 }
1040                                 if (ques=(c=='?'))
1041                                         continue;
1042                         case ESgetpars:
1043                                 if (c==';' && npar<NPAR-1) {
1044                                         npar++;
1045                                         continue;
1046                                 } else if (c>='0' && c<='9') {
1047                                         par[npar] *= 10;
1048                                         par[npar] += c-'0';
1049                                         continue;
1050                                 } else state=ESgotpars;
1051                         case ESgotpars:
1052                                 state = ESnormal;
1053                                 switch(c) {
1054                                         case 'h':
1055                                                 set_mode(currcons,1);
1056                                                 continue;
1057                                         case 'l':
1058                                                 set_mode(currcons,0);
1059                                                 continue;
1060                                         case 'n':
1061                                                 if (!ques)
1062                                                         if (par[0] == 5)
1063                                                                 status_report(currcons,tty);
1064                                                         else if (par[0] == 6)
1065                                                                 cursor_report(currcons,tty);
1066                                                 continue;
1067                                 }
1068                                 if (ques) {
1069                                         ques = 0;
1070                                         continue;
1071                                 }
1072                                 switch(c) {
1073                                         case 'G': case '`':
1074                                                 if (par[0]) par[0]--;
1075                                                 gotoxy(currcons,par[0],y);
1076                                                 continue;
1077                                         case 'A':
1078                                                 if (!par[0]) par[0]++;
1079                                                 gotoxy(currcons,x,y-par[0]);
1080                                                 continue;
1081                                         case 'B': case 'e':
1082                                                 if (!par[0]) par[0]++;
1083                                                 gotoxy(currcons,x,y+par[0]);
1084                                                 continue;
1085                                         case 'C': case 'a':
1086                                                 if (!par[0]) par[0]++;
1087                                                 gotoxy(currcons,x+par[0],y);
1088                                                 continue;
1089                                         case 'D':
1090                                                 if (!par[0]) par[0]++;
1091                                                 gotoxy(currcons,x-par[0],y);
1092                                                 continue;
1093                                         case 'E':
1094                                                 if (!par[0]) par[0]++;
1095                                                 gotoxy(currcons,0,y+par[0]);
1096                                                 continue;
1097                                         case 'F':
1098                                                 if (!par[0]) par[0]++;
1099                                                 gotoxy(currcons,0,y-par[0]);
1100                                                 continue;
1101                                         case 'd':
1102                                                 if (par[0]) par[0]--;
1103                                                 gotoxy(currcons,x,par[0]);
1104                                                 continue;
1105                                         case 'H': case 'f':
1106                                                 if (par[0]) par[0]--;
1107                                                 if (par[1]) par[1]--;
1108                                                 gotoxy(currcons,par[1],par[0]);
1109                                                 continue;
1110                                         case 'J':
1111                                                 csi_J(currcons,par[0]);
1112                                                 continue;
1113                                         case 'K':
1114                                                 csi_K(currcons,par[0]);
1115                                                 continue;
1116                                         case 'L':
1117                                                 csi_L(currcons,par[0]);
1118                                                 continue;
1119                                         case 'M':
1120                                                 csi_M(currcons,par[0]);
1121                                                 continue;
1122                                         case 'P':
1123                                                 csi_P(currcons,par[0]);
1124                                                 continue;
1125                                         case 'c':
1126                                                 if (!par[0])
1127                                                         respond_ID(currcons,tty);
1128                                                 continue;
1129                                         case 'g':
1130                                                 if (!par[0])
1131                                                         tab_stop[x >> 5] &= ~(1 << (x & 31));
1132                                                 else if (par[0] == 3) {
1133                                                         tab_stop[0] =
1134                                                         tab_stop[1] =
1135                                                         tab_stop[2] =
1136                                                         tab_stop[3] =
1137                                                         tab_stop[4] = 0;
1138                                                 }
1139                                                 continue;
1140                                         case 'm':
1141                                                 csi_m(currcons);
1142                                                 continue;
1143                                         case 'r':
1144                                                 if (!par[0])
1145                                                         par[0]++;
1146                                                 if (!par[1])
1147                                                         par[1] = video_num_lines;
1148                                                 /* Minimum allowed region is 2 lines */
1149                                                 if (par[0] < par[1] &&
1150                                                     par[1] <= video_num_lines) {
1151                                                         top=par[0]-1;
1152                                                         bottom=par[1];
1153                                                         gotoxy(currcons,0,0);
1154                                                 }
1155                                                 continue;
1156                                         case 's':
1157                                                 save_cur(currcons);
1158                                                 continue;
1159                                         case 'u':
1160                                                 restore_cur(currcons);
1161                                                 continue;
1162                                         case '@':
1163                                                 csi_at(currcons,par[0]);
1164                                                 continue;
1165                                         case ']': /* setterm functions */
1166                                                 setterm_command(currcons);
1167                                                 continue;
1168                                 }
1169                                 continue;
1170                         case ESfunckey:
1171                                 state = ESnormal;
1172                                 continue;
1173                         case EShash:
1174                                 state = ESnormal;
1175                                 if (c == '8') {
1176                                         /* DEC screen alignment test. kludge :-) */
1177                                         video_erase_char =
1178                                                 (video_erase_char & 0xff00) | 'E';
1179                                         csi_J(currcons, 2);
1180                                         video_erase_char =
1181                                                 (video_erase_char & 0xff00) | ' ';
1182                                 }
1183                                 continue;
1184                         case ESsetG0:
1185                                 if (c == '0')
1186                                         G0_charset = GRAF_TRANS;
1187                                 else if (c == 'B')
1188                                         G0_charset = NORM_TRANS;
1189                                 else if (c == 'U')
1190                                         G0_charset = NULL_TRANS;
1191                                 if (charset == 0)
1192                                         translate = G0_charset;
1193                                 state = ESnormal;
1194                                 continue;
1195                         case ESsetG1:
1196                                 if (c == '0')
1197                                         G1_charset = GRAF_TRANS;
1198                                 else if (c == 'B')
1199                                         G1_charset = NORM_TRANS;
1200                                 else if (c == 'U')
1201                                         G1_charset = NULL_TRANS;
1202                                 if (charset == 1)
1203                                         translate = G1_charset;
1204                                 state = ESnormal;
1205                                 continue;
1206                         default:
1207                                 state = ESnormal;
1208                 }
1209         }
1210         if (vtmode == KD_GRAPHICS)
1211                 return;
1212         set_cursor(currcons);
1213 }
1214 
1215 void do_keyboard_interrupt(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1216 {
1217         TTY_READ_FLUSH(TTY_TABLE(0));
1218         timer_active &= ~(1<<BLANK_TIMER);
1219         if (vt_cons[fg_console].vt_mode == KD_GRAPHICS)
1220                 return;
1221         if (console_blanked) {
1222                 timer_table[BLANK_TIMER].expires = 0;
1223                 timer_active |= 1<<BLANK_TIMER;
1224         } else if (blankinterval) {
1225                 timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
1226                 timer_active |= 1<<BLANK_TIMER;
1227         }
1228 }       
1229 
1230 void * memsetw(void * s,unsigned short c,int count)
     /* [previous][next][first][last][top][bottom][index][help] */
1231 {
1232 __asm__("cld\n\t"
1233         "rep\n\t"
1234         "stosw"
1235         ::"a" (c),"D" (s),"c" (count)
1236         :"cx","di");
1237 return s;
1238 }
1239 
1240 /*
1241  *  long con_init(long);
1242  *
1243  * This routine initalizes console interrupts, and does nothing
1244  * else. If you want the screen to clear, call tty_write with
1245  * the appropriate escape-sequece.
1246  *
1247  * Reads the information preserved by setup.s to determine the current display
1248  * type and sets everything accordingly.
1249  */
1250 long con_init(long kmem_start)
     /* [previous][next][first][last][top][bottom][index][help] */
1251 {
1252         register unsigned char a;
1253         char *display_desc = "????";
1254         char *display_ptr;
1255         int currcons = 0;
1256         long base;
1257         int orig_x = ORIG_X;
1258         int orig_y = ORIG_Y;
1259 
1260         vc_scrmembuf = (unsigned short *) kmem_start;
1261         video_num_columns = ORIG_VIDEO_COLS;
1262         video_size_row = video_num_columns * 2;
1263         video_num_lines = ORIG_VIDEO_LINES;
1264         video_page = ORIG_VIDEO_PAGE;
1265         screen_size = (video_num_lines * video_size_row);
1266         kmem_start += NR_CONSOLES * screen_size;
1267         timer_table[BLANK_TIMER].fn = blank_screen;
1268         timer_table[BLANK_TIMER].expires = 0;
1269         if (blankinterval) {
1270                 timer_table[BLANK_TIMER].expires = jiffies+blankinterval;
1271                 timer_active |= 1<<BLANK_TIMER;
1272         }
1273         
1274         if (ORIG_VIDEO_MODE == 7)       /* Is this a monochrome display? */
1275         {
1276                 video_mem_base = 0xb0000;
1277                 video_port_reg = 0x3b4;
1278                 video_port_val = 0x3b5;
1279                 if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
1280                 {
1281                         video_type = VIDEO_TYPE_EGAM;
1282                         video_mem_term = 0xb8000;
1283                         display_desc = "EGAm";
1284                 }
1285                 else
1286                 {
1287                         video_type = VIDEO_TYPE_MDA;
1288                         video_mem_term = 0xb2000;
1289                         display_desc = "*MDA";
1290                 }
1291         }
1292         else                            /* If not, it is color. */
1293         {
1294                 can_do_color = 1;
1295                 video_mem_base = 0xb8000;
1296                 video_port_reg  = 0x3d4;
1297                 video_port_val  = 0x3d5;
1298                 if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
1299                 {
1300                         video_type = VIDEO_TYPE_EGAC;
1301                         video_mem_term = 0xc0000;
1302                         display_desc = "EGAc";
1303                 }
1304                 else
1305                 {
1306                         video_type = VIDEO_TYPE_CGA;
1307                         video_mem_term = 0xba000;
1308                         display_desc = "*CGA";
1309                 }
1310         }
1311         
1312         /* Let the user know what kind of display driver we are using */
1313         
1314         display_ptr = ((char *)video_mem_base) + video_size_row - 8;
1315         while (*display_desc)
1316         {
1317                 *display_ptr++ = *display_desc++;
1318                 display_ptr++;
1319         }
1320 
1321         /* Initialize the variables used for scrolling (mostly EGA/VGA) */
1322 
1323         base = (long)vc_scrmembuf;
1324         for (currcons = 0; currcons<NR_CONSOLES; currcons++) {
1325                 pos = origin = video_mem_start = base;
1326                 scr_end = video_mem_end = (base += screen_size);
1327                 vc_scrbuf[currcons] = (unsigned short *) origin;
1328                 vtmode          = KD_TEXT;
1329                 kbdraw          = 0;
1330                 def_color       = 0x07;   /* white */
1331                 ulcolor         = 0x0f;   /* bold white */
1332                 halfcolor       = 0x08;   /* grey */
1333                 reset_terminal(currcons, currcons);
1334         }
1335         currcons = fg_console = 0;
1336 
1337         video_mem_start = video_mem_base;
1338         video_mem_end = video_mem_term;
1339         origin = video_mem_start;
1340         scr_end = video_mem_start + video_num_lines * video_size_row;
1341         gotoxy(currcons,0,0);
1342         save_cur(currcons);
1343         gotoxy(currcons,orig_x,orig_y);
1344         update_screen(fg_console);
1345 
1346         if (request_irq(KEYBOARD_IRQ,keyboard_interrupt))
1347                 printk("Unable to get IRQ%d for keyboard driver\n",KEYBOARD_IRQ);
1348         a=inb_p(0x61);
1349         outb_p(a|0x80,0x61);
1350         outb_p(a,0x61);
1351         return kmem_start;
1352 }
1353 
1354 void kbdsave(int new_console)
     /* [previous][next][first][last][top][bottom][index][help] */
1355 {
1356         int currcons = fg_console;
1357         kbdmode = kmode;
1358         kbdraw = kraw;
1359         kbdleds = kleds;
1360         kbdapplic = kapplic;
1361         decckm = ckmode;
1362         decarm = krepeat;
1363         lnm = lfnlmode;
1364         currcons = new_console;
1365         kmode = (kmode & 0x3F) | (kbdmode & 0xC0);
1366         kraw = kbdraw;
1367         kleds = kbdleds;
1368         kapplic = kbdapplic;
1369         ckmode = decckm;
1370         krepeat = decarm;
1371         lfnlmode = lnm;
1372         set_leds();
1373 }
1374 
1375 static void get_scrmem(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
1376 {
1377         memcpy((void *)vc_scrbuf[fg_console],(void *)origin, screen_size);
1378         video_mem_start = (unsigned long)vc_scrbuf[fg_console];
1379         origin  = video_mem_start;
1380         scr_end = video_mem_end = video_mem_start+screen_size;
1381         pos = origin + y*video_size_row + (x<<1);
1382 }
1383 
1384 static void set_scrmem(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
1385 {
1386         video_mem_start = video_mem_base;
1387         video_mem_end = video_mem_term;
1388         origin  = video_mem_start;
1389         scr_end = video_mem_start + screen_size;
1390         pos = origin + y*video_size_row + (x<<1);
1391         memcpy((void *)video_mem_base, (void *)vc_scrbuf[fg_console], screen_size);
1392 }
1393 
1394 void blank_screen(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1395 {
1396         timer_table[BLANK_TIMER].fn = unblank_screen;
1397         get_scrmem(fg_console);
1398         hide_cursor(fg_console);
1399         console_blanked = 1;
1400         memsetw((void *)video_mem_base, 0x0020, video_mem_term-video_mem_base );
1401 }
1402 
1403 void unblank_screen(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1404 {
1405         timer_table[BLANK_TIMER].fn = blank_screen;
1406         if (blankinterval) {
1407                 timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
1408                 timer_active |= 1<<BLANK_TIMER;
1409         }
1410         console_blanked = 0;
1411         set_scrmem(fg_console);
1412         set_origin(fg_console);
1413         set_cursor(fg_console);
1414 }
1415 
1416 void update_screen(int new_console)
     /* [previous][next][first][last][top][bottom][index][help] */
1417 {
1418         static int lock = 0;
1419 
1420         if (new_console == fg_console || lock)
1421                 return;
1422         lock = 1;
1423         kbdsave(new_console);
1424         get_scrmem(fg_console); 
1425         fg_console = new_console;
1426         set_scrmem(fg_console); 
1427         set_origin(fg_console);
1428         set_cursor(new_console);
1429         lock = 0;
1430 }
1431 
1432 /* from bsd-net-2: */
1433 
1434 static void sysbeepstop(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1435 {
1436         /* disable counter 2 */
1437         outb(inb_p(0x61)&0xFC, 0x61);
1438 }
1439 
1440 static void sysbeep(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1441 {
1442         /* enable counter 2 */
1443         outb_p(inb_p(0x61)|3, 0x61);
1444         /* set command for counter 2, 2 byte write */
1445         outb_p(0xB6, 0x43);
1446         /* send 0x637 for 750 HZ */
1447         outb_p(0x37, 0x42);
1448         outb(0x06, 0x42);
1449         /* 1/8 second */
1450         timer_table[BEEP_TIMER].expires = jiffies + HZ/8;
1451         timer_table[BEEP_TIMER].fn = sysbeepstop;
1452         timer_active |= 1<<BEEP_TIMER;
1453 }
1454 
1455 int do_screendump(int arg)
     /* [previous][next][first][last][top][bottom][index][help] */
1456 {
1457         char *sptr, *buf = (char *)arg;
1458         int currcons, l;
1459 
1460         verify_area(buf,2+video_num_columns*video_num_lines);
1461         currcons = get_fs_byte(buf+1);
1462         if ((currcons<0) || (currcons>=NR_CONSOLES))
1463                 return -EIO;
1464         put_fs_byte((char)(video_num_lines),buf++);     
1465         put_fs_byte((char)(video_num_columns),buf++);
1466         currcons = (currcons ? currcons-1 : fg_console);
1467         sptr = (char *) origin;
1468         for (l=video_num_lines*video_num_columns; l>0 ; l--, sptr++)
1469                 put_fs_byte(*sptr++,buf++);     
1470         return(0);
1471 }
1472 
1473 void console_print(const char * b)
     /* [previous][next][first][last][top][bottom][index][help] */
1474 {
1475         int currcons = fg_console;
1476         char c;
1477 
1478         if (currcons<0 || currcons>=NR_CONSOLES)
1479                 currcons = 0;
1480         while (c = *(b++)) {
1481                 if (c == 10 || c == 13 || need_wrap) {
1482                         if (c != 13)
1483                                 lf(currcons);
1484                         cr(currcons);
1485                         if (c == 10 || c == 13)
1486                                 continue;
1487                 }
1488                 *(char *) pos = c;
1489                 *(char *) (pos+1) = attr;
1490                 if (x == video_num_columns - 1) {
1491                         need_wrap = 1;
1492                         continue;
1493                 }
1494                 x++;
1495                 pos+=2;
1496         }
1497         set_cursor(currcons);
1498         if (vt_cons[fg_console].vt_mode == KD_GRAPHICS)
1499                 return;
1500         timer_active &= ~(1<<BLANK_TIMER);
1501         if (console_blanked) {
1502                 timer_table[BLANK_TIMER].expires = 0;
1503                 timer_active |= 1<<BLANK_TIMER;
1504         } else if (blankinterval) {
1505                 timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
1506                 timer_active |= 1<<BLANK_TIMER;
1507         }
1508 }
1509 
1510 /*
1511  * All we do is set the write and ioctl subroutines; later on maybe we'll
1512  * dynamically allocate the console screen memory.
1513  */
1514 int con_open(struct tty_struct *tty, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
1515 {
1516         tty->write = con_write;
1517         tty->ioctl = vt_ioctl;
1518         return 0;
1519 }

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