root/arch/m68k/kernel/console.c

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

DEFINITIONS

This source file includes following definitions.
  1. vc_allocate
  2. vc_resize
  3. vc_resize_con
  4. vc_disallocate
  5. gotoxy
  6. hide_cursor
  7. set_cursor
  8. no_scroll
  9. scrollfront
  10. scrollback
  11. scrup
  12. scrdown
  13. lf
  14. ri
  15. cr
  16. bs
  17. del
  18. csi_J
  19. csi_K
  20. csi_X
  21. update_attr
  22. default_attr
  23. csi_m
  24. respond_string
  25. cursor_report
  26. status_report
  27. respond_ID
  28. mouse_report
  29. mouse_reporting
  30. screenpos
  31. invert_screen
  32. complement_pos
  33. screen_word
  34. scrw2glyph
  35. screen_pos
  36. getconsxy
  37. putconsxy
  38. set_mode
  39. setterm_command
  40. insert_char
  41. csi_at
  42. csi_L
  43. csi_P
  44. csi_M
  45. save_cur
  46. restore_cur
  47. reset_terminal
  48. con_stop
  49. con_start
  50. con_write
  51. con_write_room
  52. con_chars_in_buffer
  53. poke_blanked_console
  54. console_print
  55. con_throttle
  56. con_unthrottle
  57. vc_init
  58. console_bh
  59. con_init
  60. do_blank_screen
  61. do_unblank_screen
  62. update_screen
  63. blank_screen
  64. unblank_screen
  65. con_open
  66. set_get_font
  67. con_set_cmap
  68. con_get_cmap
  69. reset_palette
  70. set_palette
  71. con_set_font
  72. con_get_font
  73. con_adjust_height
  74. set_vesa_blanking
  75. get_video_num_lines
  76. get_video_num_columns
  77. get_video_size_row

   1 /*
   2  *  linux/drivers/char/console.c
   3  *
   4  *  Copyright (C) 1991, 1992  Linus Torvalds
   5  */
   6 /*
   7  *      console.c
   8  *
   9  * This module exports the console io functions:
  10  *
  11  *     'void do_keyboard_interrupt(void)'
  12  *
  13  *     'int vc_allocate(unsigned int console)'
  14  *     'int vc_cons_allocated(unsigned int console)'
  15  *     'int vc_resize(unsigned long lines, unsigned long cols)'
  16  *     'int vc_resize_con(unsigned long lines, unsigned long cols,
  17  *                        unsigned int currcons)'
  18  *     'void vc_disallocate(unsigned int currcons)'
  19  *
  20  *     'unsigned long con_init(unsigned long)'
  21  *     'int con_open(struct tty_struct *tty, struct file * filp)'
  22  *     'void con_write(struct tty_struct * tty)'
  23  *     'void console_print(const char * b)'
  24  *     'void update_screen(int new_console)'
  25  *
  26  *     'void do_blank_screen(int)'
  27  *     'void do_unblank_screen(void)'
  28  *     'void poke_blanked_console(void)'
  29  *
  30  *     'unsigned short *screen_pos(int currcons, int w_offset, int viewed)'
  31  *     'void complement_pos(int currcons, int offset)'
  32  *     'void invert_screen(int currcons, int offset, int count, int shift)'
  33  *
  34  *     'void scrollback(int lines)'
  35  *     'void scrollfront(int lines)'
  36  *
  37  *     'int con_get_font(char *)' 
  38  *     'int con_set_font(char *)'
  39  * 
  40  *     'void mouse_report(struct tty_struct * tty, int butt, int mrx, int mry)'
  41  *     'int mouse_reporting(void)'
  42  *
  43  *     'unsigned long get_video_num_lines(unsigned int console)'
  44  *     'unsigned long get_video_num_columns(unsigned int console)'
  45  *     'unsigned long get_video_size_row(unsigned int console)'
  46  *
  47  * Hopefully this will be a rather complete VT102 implementation.
  48  *
  49  * Beeping thanks to John T Kohl.
  50  *
  51  * Virtual Consoles, Screen Blanking, Screen Dumping, Color, Graphics
  52  *   Chars, and VT100 enhancements by Peter MacDonald.
  53  *
  54  * Copy and paste function by Andrew Haylett,
  55  *   some enhancements by Alessandro Rubini.
  56  *
  57  * User definable mapping table and font loading by Eugene G. Crosser,
  58  * <crosser@pccross.msk.su>
  59  *
  60  * Code to check for different video-cards mostly by Galen Hunt,
  61  * <g-hunt@ee.utah.edu>
  62  *
  63  * Rudimentary ISO 10646/Unicode/UTF-8 character set support by
  64  * Markus Kuhn, <mskuhn@immd4.informatik.uni-erlangen.de>.
  65  *
  66  * Dynamic allocation of consoles, aeb@cwi.nl, May 1994
  67  * Resizing of consoles, aeb, 940926
  68  *
  69  * Code for xterm like mouse click reporting by Peter Orbaek 20-Jul-94
  70  * <poe@daimi.aau.dk>
  71  *
  72  * 680x0 LINUX support by Arno Griffioen (arno@usn.nl)
  73  *
  74  * 9-Apr-94:  Arno Griffioen: fixed scrolling and delete-char bug.
  75  *            Scrolling code moved to amicon.c
  76  *
  77  * 18-Apr-94: David Carter [carter@cs.bris.ac.uk]. 680x0 LINUX modified 
  78  *            Integrated support for new low level driver `amicon_ocs.c'
  79  *
  80  */
  81 
  82 #define BLANK 0x0020
  83 #undef CAN_LOAD_EGA_FONTS    /* undefine if the user must not do this */
  84 
  85 /* A bitmap for codes <32. A bit of 1 indicates that the code
  86  * corresponding to that bit number invokes some special action
  87  * (such as cursor movement) and should not be displayed as a
  88  * glyph unless the disp_ctrl mode is explicitly enabled.
  89  */
  90 #define CTRL_ACTION 0x0d00ff81
  91 #define CTRL_ALWAYS 0x0800f501  /* Cannot be overridden by disp_ctrl */
  92 
  93 /*
  94  * Here is the default bell parameters: 750HZ, 1/8th of a second
  95  */
  96 #define DEFAULT_BELL_PITCH      750
  97 #define DEFAULT_BELL_DURATION   (HZ/8)
  98 
  99 /*
 100  *  NOTE!!! We sometimes disable and enable interrupts for a short while
 101  * (to put a word in video IO), but this will work even for keyboard
 102  * interrupts. We know interrupts aren't enabled when getting a keyboard
 103  * interrupt, as we use trap-gates. Hopefully all is well.
 104  */
 105 
 106 #include <linux/sched.h>
 107 #include <linux/timer.h>
 108 #include <linux/interrupt.h>
 109 #include <linux/tty.h>
 110 #include <linux/tty_flip.h>
 111 #include <linux/kernel.h>
 112 #include <linux/string.h>
 113 #include <linux/errno.h>
 114 #include <linux/console.h>
 115 #include <linux/kd.h>
 116 #include <linux/malloc.h>
 117 #include <linux/major.h>
 118 #include <linux/mm.h>
 119 #include <linux/ioport.h>
 120 
 121 #include <asm/io.h>
 122 #include <asm/segment.h>
 123 #include <asm/system.h>
 124 #include <asm/bitops.h>
 125 
 126 #include "../../../drivers/char/kbd_kern.h"
 127 #include "../../../drivers/char/vt_kern.h"
 128 #include "../../../drivers/char/consolemap.h"
 129 #include "../../../drivers/char/selection.h"
 130 
 131 
 132 #ifndef MIN
 133 #define MIN(a,b)        ((a) < (b) ? (a) : (b))
 134 #endif
 135 
 136 struct tty_driver console_driver;
 137 static int console_refcount;
 138 static struct tty_struct *console_table[MAX_NR_CONSOLES];
 139 static struct termios *console_termios[MAX_NR_CONSOLES];
 140 static struct termios *console_termios_locked[MAX_NR_CONSOLES];
 141 
 142 static void vc_init(unsigned int console, int do_clear);
 143 
 144 static void update_attr(int currcons);
 145 static void gotoxy(int currcons, int new_x, int new_y);
 146 static void save_cur(int currcons);
 147 static void blank_screen(void);
 148 static void unblank_screen(void);
 149 extern void change_console(unsigned int);
 150 static inline void set_cursor(int currcons);
 151 static void reset_terminal(int currcons, int do_clear);
 152 extern void reset_vc(unsigned int new_console);
 153 extern void vt_init(void);
 154 extern void register_console(void (*proc)(const char *));
 155 extern void vesa_blank(void);
 156 extern void vesa_unblank(void);
 157 extern void compute_shiftstate(void);
 158 void poke_blanked_console(void);
 159 void do_blank_screen(int);
 160 
 161 unsigned long   video_num_lines;
 162 unsigned long   video_num_columns;
 163 unsigned long   video_size_row;
 164 
 165 static int printable = 0;                       /* Is console ready for printing? */
 166 unsigned long video_font_height;        /* Height of current screen font */
 167 unsigned long video_scan_lines;         /* Number of scan lines on screen */
 168 unsigned long default_font_height;      /* Height of default screen font */
 169 int           video_mode_512ch = 0;     /* 512-character mode */
 170 static unsigned short console_charmask = 0x0ff;
 171 
 172 static unsigned short *vc_scrbuf[MAX_NR_CONSOLES];
 173 
 174 /* used by kbd_bh - set by keyboard_interrupt */
 175        int do_poke_blanked_console = 0;
 176        int console_blanked = 0;
 177 static int blankinterval = 10*60*HZ;
 178 
 179 static struct vc {
 180         struct vc_data *d;
 181 
 182         /* might add  scrmem, vt_struct, kbd  at some time,
 183            to have everything in one place - the disadvantage
 184            would be that vc_cons etc can no longer be static */
 185 } vc_cons [MAX_NR_CONSOLES];
 186 struct consw *conswitchp;
 187 
 188 #define cols            (vc_cons[currcons].d->vc_cols)
 189 #define rows            (vc_cons[currcons].d->vc_rows)
 190 #define size_row        (vc_cons[currcons].d->vc_size_row)
 191 #define screenbuf_size  (vc_cons[currcons].d->vc_screenbuf_size)
 192 #define cons_num        (vc_cons[currcons].d->vc_num)
 193 #define origin          (vc_cons[currcons].d->vc_origin)
 194 #define scr_end         (vc_cons[currcons].d->vc_scr_end)
 195 #define pos             (vc_cons[currcons].d->vc_pos)
 196 #define top             (vc_cons[currcons].d->vc_top)
 197 #define bottom          (vc_cons[currcons].d->vc_bottom)
 198 #define x               (vc_cons[currcons].d->vc_x)
 199 #define y               (vc_cons[currcons].d->vc_y)
 200 #define vc_state        (vc_cons[currcons].d->vc_state)
 201 #define npar            (vc_cons[currcons].d->vc_npar)
 202 #define par             (vc_cons[currcons].d->vc_par)
 203 #define ques            (vc_cons[currcons].d->vc_ques)
 204 #define attr            (vc_cons[currcons].d->vc_attr)
 205 #define saved_x         (vc_cons[currcons].d->vc_saved_x)
 206 #define saved_y         (vc_cons[currcons].d->vc_saved_y)
 207 #define translate       (vc_cons[currcons].d->vc_translate)
 208 #define G0_charset      (vc_cons[currcons].d->vc_G0_charset)
 209 #define G1_charset      (vc_cons[currcons].d->vc_G1_charset)
 210 #define saved_G0        (vc_cons[currcons].d->vc_saved_G0)
 211 #define saved_G1        (vc_cons[currcons].d->vc_saved_G1)
 212 #define utf             (vc_cons[currcons].d->vc_utf)
 213 #define utf_count       (vc_cons[currcons].d->vc_utf_count)
 214 #define utf_char        (vc_cons[currcons].d->vc_utf_char)
 215 #define video_mem_start (vc_cons[currcons].d->vc_video_mem_start)
 216 #define video_mem_end   (vc_cons[currcons].d->vc_video_mem_end)
 217 #define video_erase_char (vc_cons[currcons].d->vc_video_erase_char)     
 218 #define disp_ctrl       (vc_cons[currcons].d->vc_disp_ctrl)
 219 #define toggle_meta     (vc_cons[currcons].d->vc_toggle_meta)
 220 #define decscnm         (vc_cons[currcons].d->vc_decscnm)
 221 #define decom           (vc_cons[currcons].d->vc_decom)
 222 #define decawm          (vc_cons[currcons].d->vc_decawm)
 223 #define deccm           (vc_cons[currcons].d->vc_deccm)
 224 #define decim           (vc_cons[currcons].d->vc_decim)
 225 #define deccolm         (vc_cons[currcons].d->vc_deccolm)
 226 #define need_wrap       (vc_cons[currcons].d->vc_need_wrap)
 227 #define has_scrolled    (vc_cons[currcons].d->vc_has_scrolled)
 228 #define kmalloced       (vc_cons[currcons].d->vc_kmalloced)
 229 #define report_mouse    (vc_cons[currcons].d->vc_report_mouse)
 230 #define can_do_color    (vc_cons[currcons].d->vc_can_do_color)
 231 #define color           (vc_cons[currcons].d->vc_color)
 232 #define s_color         (vc_cons[currcons].d->vc_s_color)
 233 #define def_color       (vc_cons[currcons].d->vc_def_color)
 234 #define foreground      (color & 0x0f)
 235 #define background      (color & 0xf0)
 236 #define charset         (vc_cons[currcons].d->vc_charset)
 237 #define s_charset       (vc_cons[currcons].d->vc_s_charset)
 238 #define intensity       (vc_cons[currcons].d->vc_intensity)
 239 #define underline       (vc_cons[currcons].d->vc_underline)
 240 #define blink           (vc_cons[currcons].d->vc_blink)
 241 #define reverse         (vc_cons[currcons].d->vc_reverse)
 242 #define s_intensity     (vc_cons[currcons].d->vc_s_intensity)
 243 #define s_underline     (vc_cons[currcons].d->vc_s_underline)
 244 #define s_blink         (vc_cons[currcons].d->vc_s_blink)
 245 #define s_reverse       (vc_cons[currcons].d->vc_s_reverse)
 246 #define ulcolor         (vc_cons[currcons].d->vc_ulcolor)
 247 #define halfcolor       (vc_cons[currcons].d->vc_halfcolor)
 248 #define tab_stop        (vc_cons[currcons].d->vc_tab_stop)
 249 #define bell_pitch      (vc_cons[currcons].d->vc_bell_pitch)
 250 #define bell_duration   (vc_cons[currcons].d->vc_bell_duration)
 251 #define sw              (vc_cons[currcons].d->vc_sw)
 252 
 253 #define vcmode          (vt_cons[currcons]->vc_mode)
 254 #if 0 /* XXX */
 255 #define vtmode          (vt_cons[currcons]->vt_mode)
 256 #define vtpid           (vt_cons[currcons]->vt_pid)
 257 #define vtnewvt         (vt_cons[currcons]->vt_newvt)
 258 #endif
 259 
 260 #define structsize      (sizeof(struct vc_data) + sizeof(struct vt_struct))
 261 
 262 int vc_cons_allocated(unsigned int i)
 263 {
 264         return (i < MAX_NR_CONSOLES && vc_cons[i].d);
 265 }
 266 
 267 int vc_allocate(unsigned int currcons)          /* return 0 on success */
     /* [previous][next][first][last][top][bottom][index][help] */
 268 {
 269         if (currcons >= MAX_NR_CONSOLES)
 270           return -ENODEV;
 271         if (!vc_cons[currcons].d) {
 272             long p, q;
 273 
 274             /* prevent users from taking too much memory */
 275             if (currcons >= MAX_NR_USER_CONSOLES && !suser())
 276               return -EPERM;
 277 
 278             /* due to the granularity of kmalloc, we waste some memory here */
 279             /* the alloc is done in two steps, to optimize the common situation
 280                of a 25x80 console (structsize=216, screenbuf_size=4000) */
 281             p = (long) kmalloc(structsize, GFP_KERNEL);
 282             if (!p)
 283                 return -ENOMEM;
 284             vc_cons[currcons].d = (struct vc_data *) p;
 285             vt_cons[currcons] = (struct vt_struct *)(p+sizeof(struct vc_data));
 286 
 287             /* ++Geert: sw->con_init determines console size */
 288             sw = conswitchp;
 289             cons_num = currcons;
 290             sw->con_init (vc_cons[currcons].d);
 291             size_row = cols<<1;
 292             screenbuf_size = rows*size_row;
 293 
 294             q = (long) kmalloc(screenbuf_size, GFP_KERNEL);
 295             if (!q) {
 296                 kfree_s((char *) p, structsize);
 297                 vc_cons[currcons].d = NULL;
 298                 return -ENOMEM;
 299             }
 300             vc_scrbuf[currcons] = (unsigned short *) q;
 301             kmalloced = 1;
 302             vc_init (currcons, 1);
 303         }
 304         return 0;
 305 }
 306 
 307 /*
 308  * Change # of rows and columns (0 means the size of fg_console)
 309  * [this is to be used together with some user program
 310  * like resize that changes the hardware videomode]
 311  */
 312 int vc_resize(unsigned long lines, unsigned long columns)
     /* [previous][next][first][last][top][bottom][index][help] */
 313 {
 314         unsigned long cc, ll, ss, sr;
 315         unsigned long occ, oll, oss, osr;
 316         unsigned short *p;
 317         unsigned int currcons = fg_console, i;
 318         unsigned short *newscreens[MAX_NR_CONSOLES];
 319         long ol, nl, rlth, rrem;
 320 
 321         cc = (columns ? columns : cols);
 322         ll = (lines ? lines : rows);
 323         sr = cc << 1;
 324         ss = sr * ll;
 325 
 326         /*
 327          * Some earlier version had all consoles of potentially
 328          * different sizes, but that was really messy.
 329          * So now we only change if there is room for all consoles
 330          * of the same size.
 331          */
 332         for (currcons = 0; currcons < MAX_NR_CONSOLES; currcons++) {
 333             if (!vc_cons_allocated(currcons))
 334               newscreens[currcons] = 0;
 335             else {
 336                 p = (unsigned short *) kmalloc(ss, GFP_USER);
 337                 if (!p) {
 338                     for (i = 0; i< currcons; i++)
 339                       if (newscreens[i])
 340                         kfree_s(newscreens[i], ss);
 341                     return -ENOMEM;
 342                 }
 343                 newscreens[currcons] = p;
 344             }
 345         }
 346 
 347 #if 0 /* XXX */
 348         get_scrmem(fg_console);
 349 #endif
 350 
 351         for (currcons = 0; currcons < MAX_NR_CONSOLES; currcons++) {
 352             if (!vc_cons_allocated(currcons))
 353               continue;
 354 
 355             oll = rows;
 356             occ = cols;
 357             osr = size_row;
 358             oss = screenbuf_size;
 359 
 360             rows = ll;
 361             cols = cc;
 362             size_row = sr;
 363             screenbuf_size = ss;
 364 
 365             rlth = MIN(osr, sr);
 366             rrem = sr - rlth;
 367             ol = origin;
 368             nl = (long) newscreens[currcons];
 369             if (ll < oll)
 370               ol += (oll - ll) * osr;
 371 
 372             update_attr(currcons);
 373             while (ol < scr_end) {
 374                 /* ++Geert: TODO: Because the attributes have different meanings
 375                    on monochrome and color, they should really be converted if
 376                    can_do_color changes... */
 377                 memcpyw((unsigned short *) nl, (unsigned short *) ol, rlth);
 378                 if (rrem)
 379                   memsetw((void *)(nl + rlth), video_erase_char, rrem);
 380                 ol += osr;
 381                 nl += sr;
 382             }
 383 
 384             if (kmalloced)
 385               kfree_s(vc_scrbuf[currcons], oss);
 386             vc_scrbuf[currcons] = newscreens[currcons];
 387             kmalloced = 1;
 388             screenbuf_size = ss;
 389 
 390             origin = (long) video_mem_start = vc_scrbuf[currcons];
 391             scr_end = video_mem_end = ((long) video_mem_start) + ss;
 392 
 393             if (scr_end > nl)
 394               memsetw((void *) nl, video_erase_char, scr_end - nl);
 395 
 396             /* do part of a reset_terminal() */
 397             top = 0;
 398             bottom = rows;
 399             gotoxy(currcons, x, y);
 400             save_cur(currcons);
 401         }
 402 
 403 #if 0 /* XXX */
 404         set_scrmem(fg_console, 0);
 405         set_origin(fg_console);
 406 #endif /* XXX */
 407         update_screen(fg_console);
 408         set_cursor(fg_console);
 409 
 410         return 0;
 411 }
 412 
 413 /*
 414  * ++Geert: Change # of rows and columns for one specific console.
 415  * Of course it's not messy to have all consoles of potentially different sizes,
 416  * except on PCish hardware :-)
 417  *
 418  * This is called by the low level console driver (arch/m68k/console/fbcon.c or
 419  * arch/m68k/console/txtcon.c)
 420  */
 421 void vc_resize_con(unsigned long lines, unsigned long columns,
     /* [previous][next][first][last][top][bottom][index][help] */
 422                    unsigned int currcons)
 423 {
 424         unsigned long cc, ll, ss, sr;
 425         unsigned long occ, oll, oss, osr;
 426         unsigned short *newscreen;
 427         long ol, nl, rlth, rrem;
 428         struct winsize ws;
 429 
 430         if (!columns || !lines || currcons >= MAX_NR_CONSOLES)
 431             return;
 432 
 433         cc = columns;
 434         ll = lines;
 435         sr = cc << 1;
 436         ss = sr * ll;
 437 
 438         if (!vc_cons_allocated(currcons))
 439             newscreen = 0;
 440         else if (!(newscreen = (unsigned short *) kmalloc(ss, GFP_USER)))
 441             return;
 442 
 443         if (vc_cons_allocated(currcons)) {
 444             oll = rows;
 445             occ = cols;
 446             osr = size_row;
 447             oss = screenbuf_size;
 448 
 449             rows = ll;
 450             cols = cc;
 451             size_row = sr;
 452             screenbuf_size = ss;
 453 
 454             rlth = MIN(osr, sr);
 455             rrem = sr - rlth;
 456             ol = origin;
 457             nl = (long) newscreen;
 458             if (ll < oll)
 459               ol += (oll - ll) * osr;
 460 
 461             update_attr(currcons);
 462             while (ol < scr_end) {
 463                 /* ++Geert: TODO: Because the attributes have different meanings
 464                    on monochrome and color, they should really be converted if
 465                    can_do_color changes... */
 466                 memcpyw((unsigned short *) nl, (unsigned short *) ol, rlth);
 467                 if (rrem)
 468                   memsetw((void *)(nl + rlth), video_erase_char, rrem);
 469                 ol += osr;
 470                 nl += sr;
 471             }
 472 
 473             if (kmalloced)
 474               kfree_s(vc_scrbuf[currcons], oss);
 475             vc_scrbuf[currcons] = newscreen;
 476             kmalloced = 1;
 477             screenbuf_size = ss;
 478 
 479             origin = (long) video_mem_start = vc_scrbuf[currcons];
 480             scr_end = video_mem_end = ((long)video_mem_start) + ss;
 481 
 482             if (scr_end > nl)
 483               memsetw((void *) nl, video_erase_char, scr_end - nl);
 484 
 485             /* do part of a reset_terminal() */
 486             top = 0;
 487             bottom = rows;
 488             gotoxy(currcons, x, y);
 489             save_cur(currcons);
 490 
 491             ws.ws_row = rows;
 492             ws.ws_col = cols;
 493             if (memcmp(&ws, &console_table[currcons]->winsize, sizeof (struct winsize)) &&
 494                 console_table[currcons]->pgrp > 0)
 495                 kill_pg(console_table[currcons]->pgrp, SIGWINCH, 1);
 496             console_table[currcons]->winsize = ws;
 497         }
 498 
 499    if (currcons == fg_console)
 500       update_screen(fg_console);
 501 }
 502 
 503 void vc_disallocate(unsigned int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 504 {
 505         if (vc_cons_allocated(currcons)) {
 506             if (kmalloced)
 507               kfree_s(vc_scrbuf[currcons], screenbuf_size);
 508             if (currcons >= MIN_NR_CONSOLES)
 509               kfree_s(vc_cons[currcons].d, structsize);
 510             vc_cons[currcons].d = 0;
 511         }
 512 }
 513 
 514 
 515 #define set_kbd(x) set_vc_kbd_mode(kbd_table+currcons,x)
 516 #define clr_kbd(x) clr_vc_kbd_mode(kbd_table+currcons,x)
 517 #define is_kbd(x) vc_kbd_mode(kbd_table+currcons,x)
 518 
 519 #define decarm          VC_REPEAT
 520 #define decckm          VC_CKMODE
 521 #define kbdapplic       VC_APPLIC
 522 #define lnm             VC_CRLF
 523 
 524 /*
 525  * this is what the terminal answers to a ESC-Z or csi0c query.
 526  */
 527 #define VT100ID "\033[?1;2c"
 528 #define VT102ID "\033[?6c"
 529 
 530 static unsigned char color_table[] = { 0, 4, 2, 6, 1, 5, 3, 7,
 531                                        8,12,10,14, 9,13,11,15 };
 532 
 533 /*
 534  * gotoxy() must verify all boundaries, because the arguments
 535  * might also be negative. If the given position is out of
 536  * bounds, the cursor is placed at the nearest margin.
 537  */
 538 static void gotoxy(int currcons, int new_x, int new_y)
     /* [previous][next][first][last][top][bottom][index][help] */
 539 {
 540         int max_y;
 541 
 542         if (new_x < 0)
 543                 x = 0;
 544         else
 545                 if (new_x >= cols)
 546                         x = cols - 1;
 547                 else
 548                         x = new_x;
 549         if (decom) {
 550                 new_y += top;
 551                 max_y = bottom;
 552         } else
 553                 max_y = rows;
 554         if (new_y < 0)
 555                 y = 0;
 556         else
 557                 if (new_y >= max_y)
 558                         y = max_y - 1;
 559                 else
 560                         y = new_y;
 561         pos = video_mem_start + y * cols + x;
 562         need_wrap = 0;
 563 }
 564 
 565 static void hide_cursor(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 566 {
 567         sw->con_cursor(vc_cons[currcons].d,CM_ERASE);
 568         return;
 569 }
 570 
 571 static void set_cursor(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 572 {
 573         if (currcons != fg_console || console_blanked || vcmode == KD_GRAPHICS)
 574                 return;
 575         if (deccm)
 576                 sw->con_cursor(vc_cons[currcons].d,CM_DRAW);
 577         else
 578                 hide_cursor(currcons);
 579         return;
 580 }
 581 
 582 void no_scroll(char *str, int *ints)
     /* [previous][next][first][last][top][bottom][index][help] */
 583 {
 584   /*
 585    * no_scroll currently does nothing on the m68k.
 586    */
 587 }
 588 
 589 /*
 590  * Arno:
 591  * Why do we need these? The keyboard code doesn't seem to do anything
 592  * with them either...
 593  */
 594 void scrollfront(int l)
     /* [previous][next][first][last][top][bottom][index][help] */
 595 {
 596         return;
 597 }
 598 
 599 void scrollback(int l)
     /* [previous][next][first][last][top][bottom][index][help] */
 600 {
 601         return;
 602 }
 603 
 604 static void scrup(int currcons, unsigned int t, unsigned int b,
     /* [previous][next][first][last][top][bottom][index][help] */
 605                   int nr)
 606 {
 607         unsigned short *p;
 608         int i;
 609 
 610         if (b > rows || t >= b)
 611                 return;
 612 
 613         memmove (video_mem_start + t * cols,
 614                  video_mem_start + (t + nr) * cols,
 615                  (b - t - nr) * cols * 2);
 616 
 617         p = video_mem_start + (b - nr) * cols;
 618         for (i = nr * cols; i > 0; i--)
 619           *p++ = video_erase_char;
 620 
 621         if (currcons != fg_console)
 622           return;
 623 /*
 624  * Arno:
 625  * Scrolling has now been moved to amicon.c where it should have
 626  * been all along.
 627  */
 628         sw->con_scroll(vc_cons[currcons].d, t, b, SM_UP, nr);
 629 
 630         return;
 631         
 632 }
 633 
 634 static void scrdown(int currcons, unsigned int t, unsigned int b,
     /* [previous][next][first][last][top][bottom][index][help] */
 635                     int nr)
 636 {
 637         unsigned short *p;
 638         int i;
 639 
 640         if (b > rows || t >= b)
 641                 return;
 642 
 643         memmove (video_mem_start + (t + nr) * cols,
 644                  video_mem_start + t * cols,
 645                  (b - t - nr) * cols * 2);
 646 
 647         p = video_mem_start + t * cols;
 648         for (i = nr * cols; i > 0; i--)
 649           *p++ = video_erase_char;
 650 
 651         if (currcons != fg_console)
 652           return;
 653 /*
 654  * Arno:
 655  * Scrolling has now been moved to amicon.c where it should have
 656  * been all along.
 657  */
 658         sw->con_scroll(vc_cons[currcons].d, t, b, SM_DOWN, nr);
 659 
 660         return;
 661 }
 662 
 663 static void lf(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 664 {
 665         /* don't scroll if above bottom of scrolling region, or
 666          * if below scrolling region
 667          */
 668         if (y+1 == bottom)
 669                 scrup(currcons,top,bottom, 1);
 670         else if (y < rows-1) {
 671                 y++;
 672                 pos += cols;
 673         }
 674         need_wrap = 0;
 675 }
 676 
 677 static void ri(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 678 {
 679         /* don't scroll if below top of scrolling region, or
 680          * if above scrolling region
 681          */
 682         if (y == top)
 683                 scrdown(currcons,top,bottom, 1);
 684         else if (y > 0) {
 685                 y--;
 686                 pos -= cols;
 687         }
 688         need_wrap = 0;
 689 }
 690 
 691 static inline void cr(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 692 {
 693         pos -= x;
 694         need_wrap = x = 0;
 695 }
 696 
 697 static inline void bs(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 698 {
 699         if (x) {
 700                 pos--;
 701                 x--;
 702                 need_wrap = 0;
 703         }
 704 }
 705 
 706 static inline void del(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 707 {
 708         /* ignored */
 709 }
 710 
 711 static void csi_J(int currcons, int vpar)
     /* [previous][next][first][last][top][bottom][index][help] */
 712 {
 713         unsigned long count;
 714         unsigned short *start;
 715 
 716         switch (vpar) {
 717                 case 0: /* erase from cursor to end of display */
 718                         count = (video_mem_start
 719                                  + cols * rows
 720                                  - pos);
 721                         start = pos;
 722                         if (currcons != fg_console)
 723                           break;
 724                         /* 680x0 do in two stages */
 725                         sw->con_clear(vc_cons[currcons].d,y,x,1,cols-x);
 726                         sw->con_clear(vc_cons[currcons].d,y+1,0,rows-y-1, cols);
 727                         break;
 728                 case 1: /* erase from start to cursor */
 729                         count = pos - video_mem_start + 1;
 730                         start = video_mem_start;
 731                         if (currcons != fg_console)
 732                           break;
 733                         /* 680x0 do in two stages */
 734                         sw->con_clear(vc_cons[currcons].d,0,0,y, cols);
 735                         sw->con_clear(vc_cons[currcons].d,y,0,1,x + 1);
 736                         break;
 737                 case 2: /* erase whole display */
 738                         count = cols * rows;
 739                         start = video_mem_start;
 740                         if (currcons != fg_console)
 741                           break;
 742                         sw->con_clear(vc_cons[currcons].d,0,0,rows, cols);
 743                         break;
 744                 default:
 745                         return;
 746         }
 747         while (count-- > 0)
 748           *start++ = video_erase_char;
 749         need_wrap = 0;
 750 }
 751 
 752 static void csi_K(int currcons, int vpar)
     /* [previous][next][first][last][top][bottom][index][help] */
 753 {
 754         unsigned long count;
 755         unsigned short *start;
 756 
 757         switch (vpar) {
 758                 case 0: /* erase from cursor to end of line */
 759                         count = cols - x;
 760                         start = pos;
 761                         if (currcons != fg_console)
 762                           break;
 763                         sw->con_clear(vc_cons[currcons].d,y,x,1,cols-x);
 764                         break;
 765                 case 1: /* erase from start of line to cursor */
 766                         start = pos - x;
 767                         count = x + 1;
 768                         if (currcons != fg_console)
 769                           break;
 770                         sw->con_clear(vc_cons[currcons].d,y,0,1,x + 1);
 771                         break;
 772                 case 2: /* erase whole line */
 773                         start = pos - x;
 774                         count = cols;
 775                         if (currcons != fg_console)
 776                           break;
 777                         sw->con_clear(vc_cons[currcons].d,y,0,1,cols);
 778                         break;
 779                 default:
 780                         return;
 781         }
 782         while (count-- > 0)
 783           *start++ = video_erase_char;
 784         need_wrap = 0;
 785 }
 786 
 787 static void csi_X(int currcons, int vpar) /* erase the following vpar positions */
     /* [previous][next][first][last][top][bottom][index][help] */
 788 {                                         /* not vt100? */
 789         unsigned long count;
 790         unsigned short * start;
 791 
 792         if (!vpar)
 793                 vpar++;
 794 
 795         start=pos;
 796         count=(vpar > cols-x) ? (cols-x) : vpar;
 797 
 798         if (currcons == fg_console)
 799                 sw->con_clear(vc_cons[currcons].d,y,x,1,count);
 800 
 801         while (count-- > 0)
 802                 *start++ = video_erase_char;
 803         need_wrap = 0;
 804 }
 805 
 806 /*
 807  * Arno: 
 808  * On 680x0 attributes are currently not used. This piece of code
 809  * seems hardware independent, but uses the EGA/VGA way of representing
 810  * attributes. 
 811  * TODO: modify for 680x0 and add attribute processing to putc code.
 812  *
 813  * ++roman: I completely changed the attribute format for monochrome
 814  * mode (!can_do_color). The formerly used MDA (monochrome display
 815  * adapter) format didn't allow the combination of certain effects.
 816  * Now the attribute is just a bit vector:
 817  *  Bit 0..1: intensity (0..2)
 818  *  Bit 2   : underline
 819  *  Bit 3   : reverse
 820  *  Bit 7   : blink
 821  */
 822 static void update_attr(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 823 {
 824         if (!can_do_color) {
 825                 /* Special treatment for monochrome */
 826                 attr = intensity |
 827                         (underline ? 4 : 0) |
 828                         ((reverse ^ decscnm) ? 8 : 0) |
 829                         (blink ? 0x80 : 0);
 830                 video_erase_char = ' ' | ((reverse ^ decscnm) ? 0x800 : 0);
 831                 return;
 832         }
 833 
 834         attr = color;
 835         if (underline)
 836                 attr = (attr & 0xf0) | ulcolor;
 837         else if (intensity == 0)
 838                 attr = (attr & 0xf0) | halfcolor;
 839         if (reverse ^ decscnm)
 840                 attr = reverse_video_char(attr);
 841         if (blink)
 842                 attr ^= 0x80;
 843         if (intensity == 2)
 844                 attr ^= 0x08;
 845         if (decscnm)
 846                 video_erase_char = (reverse_video_char(color) << 8) | ' ';
 847         else
 848                 video_erase_char = (color << 8) | ' ';
 849 }
 850 
 851 static void default_attr(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 852 {
 853         intensity = 1;
 854         underline = 0;
 855         reverse = 0;
 856         blink = 0;
 857         color = def_color;
 858 }
 859 
 860 static void csi_m(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
 861 {
 862         int i;
 863 
 864         for (i=0;i<=npar;i++)
 865                 switch (par[i]) {
 866                         case 0: /* all attributes off */
 867                                 default_attr(currcons);
 868                                 break;
 869                         case 1:
 870                                 intensity = 2;
 871                                 break;
 872                         case 2:
 873                                 intensity = 0;
 874                                 break;
 875                         case 4:
 876                                 underline = 1;
 877                                 break;
 878                         case 5:
 879                                 blink = 1;
 880                                 break;
 881                         case 7:
 882                                 reverse = 1;
 883                                 break;
 884                         case 10: /* ANSI X3.64-1979 (SCO-ish?)
 885                                   * Select primary font, don't display
 886                                   * control chars if defined, don't set
 887                                   * bit 8 on output.
 888                                   */
 889                                 translate = set_translate(charset == 0
 890                                                 ? G0_charset
 891                                                 : G1_charset);
 892                                 disp_ctrl = 0;
 893                                 toggle_meta = 0;
 894                                 break;
 895                         case 11: /* ANSI X3.64-1979 (SCO-ish?)
 896                                   * Select first alternate font, let's
 897                                   * chars < 32 be displayed as ROM chars.
 898                                   */
 899                                 translate = set_translate(IBMPC_MAP);
 900                                 disp_ctrl = 1;
 901                                 toggle_meta = 0;
 902                                 break;
 903                         case 12: /* ANSI X3.64-1979 (SCO-ish?)
 904                                   * Select second alternate font, toggle
 905                                   * high bit before displaying as ROM char.
 906                                   */
 907                                 translate = set_translate(IBMPC_MAP);
 908                                 disp_ctrl = 1;
 909                                 toggle_meta = 1;
 910                                 break;
 911                         case 21:
 912                         case 22:
 913                                 intensity = 1;
 914                                 break;
 915                         case 24:
 916                                 underline = 0;
 917                                 break;
 918                         case 25:
 919                                 blink = 0;
 920                                 break;
 921                         case 27:
 922                                 reverse = 0;
 923                                 break;
 924                         case 38: /* ANSI X3.64-1979 (SCO-ish?)
 925                                   * Enables underscore, white foreground
 926                                   * with white underscore (Linux - use
 927                                   * default foreground).
 928                                   */
 929                                 color = (def_color & 0x0f) | background;
 930                                 underline = 1;
 931                                 break;
 932                         case 39: /* ANSI X3.64-1979 (SCO-ish?)
 933                                   * Disable underline option.
 934                                   * Reset colour to default? It did this
 935                                   * before...
 936                                   */
 937                                 color = (def_color & 0x0f) | background;
 938                                 underline = 0;
 939                                 break;
 940                         case 49:
 941                                 color = (def_color & 0xf0) | foreground;
 942                                 break;
 943                         default:
 944                                 if (par[i] >= 30 && par[i] <= 37)
 945                                         color = color_table[par[i]-30]
 946                                                 | background; 
 947                                 else if (par[i] >= 40 && par[i] <= 47)
 948                                         color = (color_table[par[i]-40]<<4)
 949                                                 | foreground;
 950                                 break;
 951                 }
 952         update_attr(currcons);
 953 }
 954 
 955 static void respond_string(const char * p, struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 956 {
 957         while (*p) {
 958                 tty_insert_flip_char(tty, *p, 0);
 959                 p++;
 960         }
 961         tty_schedule_flip(tty);
 962 }
 963 
 964 static void cursor_report(int currcons, struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 965 {
 966         char buf[40];
 967 
 968         sprintf(buf, "\033[%ld;%ldR", y + (decom ? top+1 : 1), x+1);
 969         respond_string(buf, tty);
 970 }
 971 
 972 static inline void status_report(struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 973 {
 974         respond_string("\033[0n", tty); /* Terminal ok */
 975 }
 976 
 977 static inline void respond_ID(struct tty_struct * tty)
     /* [previous][next][first][last][top][bottom][index][help] */
 978 {
 979         respond_string(VT102ID, tty);
 980 }
 981 
 982 void mouse_report(struct tty_struct * tty, int butt, int mrx, int mry)
     /* [previous][next][first][last][top][bottom][index][help] */
 983 {
 984         char buf[8];
 985 
 986         sprintf(buf, "\033[M%c%c%c", (char)(' ' + butt), (char)('!' + mrx),
 987                 (char)('!' + mry));
 988         respond_string(buf, tty);
 989 }
 990 
 991 /* invoked via ioctl(TIOCLINUX) */
 992 int mouse_reporting(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 993 {
 994         int currcons = fg_console;
 995 
 996         return report_mouse;
 997 }
 998 
 999 static inline unsigned short *screenpos(int currcons, int offset, int viewed)
     /* [previous][next][first][last][top][bottom][index][help] */
1000 {
1001         unsigned short *p = (unsigned short *)(origin + offset);
1002 #if 0
1003         if (viewed && currcons == fg_console)
1004                 p -= (__real_origin - __origin);
1005 #endif
1006         return p;
1007 }
1008 
1009 /* Note: inverting the screen twice should revert to the original state */
1010 void invert_screen(int currcons, int offset, int count, int viewed)
     /* [previous][next][first][last][top][bottom][index][help] */
1011 {
1012         unsigned short *p;
1013         unsigned short xx, yy, oldattr;
1014 
1015         count /= 2;
1016         p = screenpos(currcons, offset, viewed);
1017         xx = (offset >> 1) % cols;
1018         yy = (offset >> 1) / cols;
1019         oldattr = attr;
1020         if (can_do_color)
1021                 while (count--) {
1022                         unsigned short old = scr_readw(p);
1023                         unsigned short new = reverse_video_short(old);
1024                         scr_writew(new, p);
1025                         p++;
1026                         if (currcons != fg_console)
1027                                 continue;
1028                         attr = new >> 8;
1029                         sw->con_putc(vc_cons[currcons].d, new & 0xff, yy, xx);
1030                         if (++xx == cols)
1031                                 xx = 0, ++yy;
1032                 }
1033         else
1034                 while (count--) {
1035                         unsigned short old = scr_readw(p);
1036                         unsigned short new = old ^ 0x800;
1037                         scr_writew(new, p);
1038                         p++;
1039                         if (currcons != fg_console)
1040                                 continue;
1041                         attr = new >> 8;
1042                         sw->con_putc(vc_cons[currcons].d, new & 0xff, yy, xx);
1043                         if (++xx == cols)
1044                                 xx = 0, ++yy;
1045                 }
1046         attr = oldattr;
1047 }
1048 
1049 /* used by selection: complement pointer position */
1050 void complement_pos(int currcons, int offset)
     /* [previous][next][first][last][top][bottom][index][help] */
1051 {
1052         static unsigned short *p = NULL;
1053         static unsigned short old = 0;
1054         static unsigned short oldx = 0, oldy = 0;
1055         unsigned short new, oldattr;
1056 
1057         oldattr = attr;
1058         if (p) {
1059                 scr_writew(old, p);
1060                 if (currcons == fg_console) {
1061                         attr = old >> 8;
1062                         sw->con_putc(vc_cons[currcons].d, old & 0xff, oldy, oldx);
1063                         attr = oldattr;
1064                 }
1065         }
1066         if (offset == -1)
1067                 p = NULL;
1068         else {
1069                 p = screenpos(currcons, offset, 1);
1070                 old = scr_readw(p);
1071                 oldx = (offset >> 1) % cols;
1072                 oldy = (offset >> 1) / cols;
1073                 if (can_do_color)
1074                         new = old ^ 0x7700;
1075                 else
1076                         new = old ^ 0x800;
1077                 scr_writew(new, p);
1078                 if (currcons == fg_console) {
1079                         attr = new >> 8;
1080                         sw->con_putc(vc_cons[currcons].d, new & 0xff, oldy, oldx);
1081                         attr = oldattr;
1082                 }
1083         }
1084 }
1085 
1086 /* used by selection */
1087 unsigned short screen_word(int currcons, int offset, int viewed)
     /* [previous][next][first][last][top][bottom][index][help] */
1088 {
1089         return scr_readw(screenpos(currcons, offset, viewed));
1090 }
1091 
1092 /* used by selection - convert a screen word to a glyph number */
1093 int scrw2glyph(unsigned short scr_word)
     /* [previous][next][first][last][top][bottom][index][help] */
1094 {
1095         return ( video_mode_512ch )
1096                 ? ((scr_word & 0x0800) >> 3) + (scr_word & 0x00ff)
1097                 : scr_word & 0x00ff;
1098 }
1099 
1100 /* used by vcs - note the word offset */
1101 unsigned short *screen_pos(int currcons, int w_offset, int viewed)
     /* [previous][next][first][last][top][bottom][index][help] */
1102 {
1103         return screenpos(currcons, 2 * w_offset, viewed);
1104 }
1105 
1106 void getconsxy(int currcons, char *p)
     /* [previous][next][first][last][top][bottom][index][help] */
1107 {
1108         p[0] = x;
1109         p[1] = y;
1110 }
1111 
1112 void putconsxy(int currcons, char *p)
     /* [previous][next][first][last][top][bottom][index][help] */
1113 {
1114         gotoxy(currcons, p[0], p[1]);
1115         set_cursor(currcons);
1116 }
1117 
1118 static void set_mode(int currcons, int on_off)
     /* [previous][next][first][last][top][bottom][index][help] */
1119 {
1120         int i;
1121 
1122         for (i=0; i<=npar; i++)
1123                 if (ques) switch(par[i]) {      /* DEC private modes set/reset */
1124                         case 1:                 /* Cursor keys send ^[Ox/^[[x */
1125                                 if (on_off)
1126                                         set_kbd(decckm);
1127                                 else
1128                                         clr_kbd(decckm); 
1129                                 break;
1130                         case 3: /* 80/132 mode switch unimplemented */
1131                                 deccolm = on_off;
1132 #if 0
1133                                 (void) vc_resize(rows, deccolm ? 132 : 80);
1134                                 /* this alone does not suffice; some user mode
1135                                    utility has to change the hardware regs */
1136 #endif
1137                                 break;
1138                         case 5:                 /* Inverted screen on/off */
1139                                 if (decscnm != on_off) {
1140                                         decscnm = on_off;
1141                                         invert_screen(currcons, 0, screenbuf_size, 0);
1142                                         update_attr(currcons);
1143                                 }
1144                                 break;
1145                         case 6:                 /* Origin relative/absolute */
1146                                 decom = on_off;
1147                                 gotoxy(currcons,0,0);
1148                                 break;
1149                         case 7:                 /* Autowrap on/off */
1150                                 decawm = on_off;
1151                                 break;
1152                         case 8:                 /* Autorepeat on/off */
1153                                 if (on_off)
1154                                         set_kbd(decarm);
1155                                 else
1156                                         clr_kbd(decarm);
1157                                 break;
1158                         case 9:
1159                                 report_mouse = on_off ? 1 : 0;
1160                                 break;
1161                         case 25:                /* Cursor on/off */
1162                                 deccm = on_off;
1163                                 set_cursor(currcons);
1164                                 break;
1165                         case 1000:
1166                                 report_mouse = on_off ? 2 : 0;
1167                                 break;
1168                 } else switch(par[i]) {         /* ANSI modes set/reset */
1169                         case 3:                 /* Monitor (display ctrls) */
1170                                 disp_ctrl = on_off;
1171                                 break;
1172                         case 4:                 /* Insert Mode on/off */
1173                                 decim = on_off;
1174                                 break;
1175                         case 20:                /* Lf, Enter == CrLf/Lf */
1176                                 if (on_off)
1177                                         set_kbd(lnm);
1178                                 else
1179                                         clr_kbd(lnm);
1180                                 break;
1181                 }
1182 }
1183 
1184 static void setterm_command(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
1185 {
1186         switch(par[0]) {
1187                 case 1: /* set color for underline mode */
1188                         if (can_do_color && par[1] < 16) {
1189                                 ulcolor = color_table[par[1]];
1190                                 if (underline)
1191                                         update_attr(currcons);
1192                         }
1193                         break;
1194                 case 2: /* set color for half intensity mode */
1195                         if (can_do_color && par[1] < 16) {
1196                                 halfcolor = color_table[par[1]];
1197                                 if (intensity == 0)
1198                                         update_attr(currcons);
1199                         }
1200                         break;
1201                 case 8: /* store colors as defaults */
1202                         def_color = attr;
1203                         default_attr(currcons);
1204                         update_attr(currcons);
1205                         break;
1206                 case 9: /* set blanking interval */
1207                         blankinterval = ((par[1] < 60) ? par[1] : 60) * 60 * HZ;
1208                         poke_blanked_console();
1209                         break;
1210                 case 10: /* set bell frequency in Hz */
1211                         if (npar >= 1)
1212                                 bell_pitch = par[1];
1213                         else
1214                                 bell_pitch = DEFAULT_BELL_PITCH;
1215                         break;
1216                 case 11: /* set bell duration in msec */
1217                         if (npar >= 1)
1218                                 bell_duration = (par[1] < 2000) ?
1219                                         par[1]*HZ/1000 : 0;
1220                         else
1221                                 bell_duration = DEFAULT_BELL_DURATION;
1222                         break;
1223                 case 12: /* bring specified console to the front */
1224                         if (par[1] >= 1 && vc_cons_allocated(par[1]-1))
1225                                 update_screen(par[1]-1);
1226                         break;
1227                 case 13: /* unblank the screen */
1228                         unblank_screen();
1229                         break;
1230         }
1231 }
1232 
1233 static void insert_char(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
1234 {
1235         int i;
1236         unsigned short *p = pos;
1237 
1238         for (i = cols - x - 2; i >= 0; i--)
1239           p[i + 1] = p[i];
1240         *pos = video_erase_char;
1241         need_wrap = 0;
1242 
1243         if (currcons != fg_console)
1244           return;
1245 
1246         /* Arno:
1247          * Move the remainder of the line (-1 character) one spot to the right
1248          */
1249         sw->con_bmove(vc_cons[currcons].d,y,x,y,x+1,1,(cols-x-1));
1250         /*
1251          * Print the erase char on the current position
1252          */
1253         sw->con_putc(vc_cons[currcons].d,(video_erase_char & 0x00ff),y,x);
1254 }
1255 
1256 static void csi_at(int currcons, unsigned int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
1257 {
1258         int i;
1259         unsigned short *p;
1260 
1261         if (nr > cols - x)
1262                 nr = cols - x;
1263         else if (!nr)
1264                 nr = 1;
1265 
1266         p = pos + cols - x - nr;
1267         while (--p >= pos)
1268           p[nr] = *p;
1269         for (i = 0; i < nr; i++)
1270           *++p = video_erase_char;
1271         need_wrap = 0;
1272 
1273         if (currcons != fg_console)
1274           return;
1275 
1276         sw->con_bmove (vc_cons[currcons].d, y, x, y, x + nr,
1277                        1, cols - x - nr);
1278         while (nr--)
1279           sw->con_putc (vc_cons[currcons].d, video_erase_char & 0x00ff,
1280                         y, x + nr);
1281 }
1282 
1283 static void csi_L(int currcons, unsigned int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
1284 {
1285         if (nr > rows)
1286                 nr = rows;
1287         else if (!nr)
1288                 nr = 1;
1289         scrdown (currcons, y, bottom, nr);
1290         need_wrap = 0;
1291 }
1292 
1293 static void csi_P(int currcons, unsigned int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
1294 {
1295         int i;
1296         unsigned short *p, *end;
1297 
1298         if (nr > cols - x)
1299                 nr = cols - x;
1300         else if (!nr)
1301                 nr = 1;
1302 
1303         p = pos;
1304         end = pos + cols - x - nr;
1305         while (p < end)
1306           *p = p[nr], p++;
1307         for (i = 0; i < nr; i++)
1308           *p++ = video_erase_char;
1309         need_wrap = 0;
1310 
1311         if (currcons != fg_console)
1312           return;
1313 
1314         sw->con_bmove (vc_cons[currcons].d, y, x + nr, y, x,
1315                        1, cols - x - nr);
1316 
1317         while (nr--)
1318           sw->con_putc (vc_cons[currcons].d, video_erase_char & 0x00ff,
1319                         y, cols - 1 - nr);
1320 }
1321 
1322 static void csi_M(int currcons, unsigned int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
1323 {
1324         if (nr > rows)
1325                 nr = rows;
1326         else if (!nr)
1327                 nr=1;
1328         scrup (currcons, y, bottom, nr);
1329         need_wrap = 0;
1330 }
1331 
1332 static void save_cur(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
1333 {
1334         saved_x         = x;
1335         saved_y         = y;
1336         s_intensity     = intensity;
1337         s_underline     = underline;
1338         s_blink         = blink;
1339         s_reverse       = reverse;
1340         s_charset       = charset;
1341         s_color         = color;
1342         saved_G0        = G0_charset;
1343         saved_G1        = G1_charset;
1344 }
1345 
1346 static void restore_cur(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
1347 {
1348         gotoxy(currcons,saved_x,saved_y);
1349         intensity       = s_intensity;
1350         underline       = s_underline;
1351         blink           = s_blink;
1352         reverse         = s_reverse;
1353         charset         = s_charset;
1354         color           = s_color;
1355         G0_charset      = saved_G0;
1356         G1_charset      = saved_G1;
1357         translate       = set_translate(charset ? G1_charset : G0_charset);
1358         update_attr(currcons);
1359         need_wrap = 0;
1360 }
1361 
1362 enum { ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey, 
1363         EShash, ESsetG0, ESsetG1, ESpercent, ESignore, ESnonstd,
1364         ESpalette };
1365 
1366 static void reset_terminal(int currcons, int do_clear)
     /* [previous][next][first][last][top][bottom][index][help] */
1367 {
1368         top             = 0;
1369         bottom          = rows;
1370         vc_state        = ESnormal;
1371         ques            = 0;
1372         translate       = set_translate(LAT1_MAP);
1373         G0_charset      = LAT1_MAP;
1374         G1_charset      = GRAF_MAP;
1375         charset         = 0;
1376         need_wrap       = 0;
1377         report_mouse    = 0;
1378         utf             = 0;
1379         utf_count       = 0;
1380 
1381         disp_ctrl       = 0;
1382         toggle_meta     = 0;
1383 
1384         decscnm         = 0;
1385         decom           = 0;
1386         decawm          = 1;
1387         deccm           = 1;
1388         decim           = 0;
1389 
1390         set_kbd(decarm);
1391         clr_kbd(decckm);
1392         clr_kbd(kbdapplic);
1393         clr_kbd(lnm);
1394         kbd_table[currcons].lockstate = 0;
1395         kbd_table[currcons].slockstate = 0;
1396         kbd_table[currcons].ledmode = LED_SHOW_FLAGS;
1397         kbd_table[currcons].ledflagstate = kbd_table[currcons].default_ledflagstate;
1398         set_leds();
1399 
1400         default_attr(currcons);
1401         update_attr(currcons);
1402 
1403         tab_stop[0]     = 0x01010100;
1404         tab_stop[1]     =
1405         tab_stop[2]     =
1406         tab_stop[3]     =
1407         tab_stop[4]     = 0x01010101;
1408 
1409         bell_pitch = DEFAULT_BELL_PITCH;
1410         bell_duration = DEFAULT_BELL_DURATION;
1411 
1412         gotoxy(currcons,0,0);
1413         save_cur(currcons);
1414         if (do_clear)
1415             csi_J(currcons,2);
1416 }
1417 
1418 /*
1419  * Turn the Scroll-Lock LED on when the tty is stopped
1420  */
1421 static void con_stop(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
1422 {
1423         int console_num;
1424         if (!tty)
1425                 return;
1426         console_num = MINOR(tty->device) - (tty->driver.minor_start);
1427         if (!vc_cons_allocated(console_num))
1428                 return;
1429         set_vc_kbd_led(kbd_table + console_num, VC_SCROLLOCK);
1430         set_leds();
1431 }
1432 
1433 /*
1434  * Turn the Scroll-Lock LED off when the console is started
1435  */
1436 static void con_start(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
1437 {
1438         int console_num;
1439         if (!tty)
1440                 return;
1441         console_num = MINOR(tty->device) - (tty->driver.minor_start);
1442         if (!vc_cons_allocated(console_num))
1443                 return;
1444         clr_vc_kbd_led(kbd_table + console_num, VC_SCROLLOCK);
1445         set_leds();
1446 }
1447 
1448 static int con_write(struct tty_struct * tty, int from_user,
     /* [previous][next][first][last][top][bottom][index][help] */
1449                      const unsigned char *buf, int count)
1450 {
1451         int c, tc, ok, n = 0;
1452         unsigned int currcons;
1453         struct vt_struct *vt = (struct vt_struct *)tty->driver_data;
1454 
1455         currcons = vt->vc_num;
1456         if (!vc_cons_allocated(currcons)) {
1457                 /* could this happen? */
1458                 static int error = 0;
1459                 if (!error) {
1460                         error = 1;
1461                         printk("con_write: tty %d not allocated\n", currcons+1);
1462                 }
1463                 return 0;
1464         }
1465 
1466         /* undraw cursor first */
1467         if (currcons == fg_console)
1468                 hide_cursor(currcons);
1469         
1470         /* clear the selection */
1471         if (currcons == sel_cons)
1472                 clear_selection();
1473 
1474         disable_bh(CONSOLE_BH);
1475         while (count) {
1476                 enable_bh(CONSOLE_BH);
1477                 c = from_user ? get_user(buf) : *buf;
1478                 buf++; n++; count--;
1479                 disable_bh(CONSOLE_BH);
1480 
1481                 if (utf) {
1482                     /* Combine UTF-8 into Unicode */
1483                     /* Incomplete characters silently ignored */
1484                     if(c > 0x7f) {   
1485                         if (utf_count > 0 && (c & 0xc0) == 0x80) {
1486                                 utf_char = (utf_char << 6) | (c & 0x3f);
1487                                 utf_count--;
1488                                 if (utf_count == 0)
1489                                     tc = c = utf_char;
1490                                 else continue;
1491                         } else {
1492                                 if ((c & 0xe0) == 0xc0) {
1493                                     utf_count = 1;
1494                                     utf_char = (c & 0x1f);
1495                                 } else if ((c & 0xf0) == 0xe0) {
1496                                     utf_count = 2;
1497                                     utf_char = (c & 0x0f);
1498                                 } else if ((c & 0xf8) == 0xf0) {
1499                                     utf_count = 3;
1500                                     utf_char = (c & 0x07);
1501                                 } else if ((c & 0xfc) == 0xf8) {
1502                                     utf_count = 4;
1503                                     utf_char = (c & 0x03);
1504                                 } else if ((c & 0xfe) == 0xfc) {
1505                                     utf_count = 5;
1506                                     utf_char = (c & 0x01);
1507                                 } else
1508                                     utf_count = 0;
1509                                 continue;
1510                         }
1511                     } else {
1512                         tc = c;
1513                         utf_count = 0;
1514                     }
1515                 } else {        /* no utf */
1516                     tc = translate[toggle_meta ? (c|0x80) : c];
1517                 }
1518 
1519                 /* If the original code was < 32 we only allow a
1520                  * glyph to be displayed if the code is not normally
1521                  * used (such as for cursor movement) or if the
1522                  * disp_ctrl mode has been explicitly enabled.
1523                  * Note: ESC is *never* allowed to be displayed as
1524                  * that would disable all escape sequences!
1525                  * To display font position 0x1B, go into UTF mode
1526                  * and display character U+F01B, or change the mapping.
1527                  */
1528                 ok = (tc && (c >= 32 || (!utf && !(((disp_ctrl ? CTRL_ALWAYS
1529                                             : CTRL_ACTION) >> c) & 1))));
1530 
1531                 if (vc_state == ESnormal && ok) {
1532                         /* Now try to find out how to display it */
1533                         tc = conv_uni_to_pc(tc);
1534                         if ( tc == -4 )
1535                           {
1536                             /* If we got -4 (not found) then see if we have
1537                                defined a replacement character (U+FFFD) */
1538                             tc = conv_uni_to_pc(0xfffd);
1539                           }
1540                         else if ( tc == -3 )
1541                           {
1542                             /* Bad hash table -- hope for the best */
1543                             tc = c;
1544                           }
1545                         if (tc & ~console_charmask)
1546                           continue; /* Conversion failed */
1547 
1548                         if (need_wrap) {
1549                                 cr(currcons);
1550                                 lf(currcons);
1551                         }
1552                         
1553 #if 1 /* XXX */
1554                         /* DPC: 1994-04-12
1555                          *   Speed up overstrike mode, using new putcs.
1556                          *
1557                          * P.S. I hate 8 spaces per tab! Use Emacs!
1558                          */
1559                         
1560                         /* Only use this for the foreground console,
1561                            where we really draw the chars */
1562 
1563                         if (count > 2 &&
1564                             !decim && !utf && currcons == fg_console) { 
1565                                 static char putcs_buf[256];
1566                                 char   *p     = putcs_buf;
1567                                 int putcs_count  = 1;
1568                                 ushort nextx  = x + 1;
1569 
1570                                 *p++ = tc;
1571                                 *pos++ = tc | (attr << 8);
1572                                 
1573                                 if (nextx == cols) {
1574                                         sw->con_putc(vc_cons[currcons].d,
1575                                                      *putcs_buf, y, x);
1576                                         pos--;
1577                                         need_wrap = decawm;
1578                                         continue;
1579                                 }
1580                                 
1581                                 /* TAB TAB TAB - Arghh!!!! */
1582                                 
1583                                 while (count)
1584                                 {
1585                                         enable_bh(CONSOLE_BH);
1586                                         c = from_user ? get_user(buf) : *buf;
1587                                         disable_bh(CONSOLE_BH);
1588                                         tc = translate[toggle_meta ? (c|0x80) : c];
1589                                         if (!tc ||
1590                                             !(c >= 32
1591                                               || !(((disp_ctrl ? CTRL_ALWAYS
1592                                                    : CTRL_ACTION) >> c) & 1)))
1593                                           break;
1594                                         tc = conv_uni_to_pc(tc);
1595                                         if (tc == -4)
1596                                           tc = conv_uni_to_pc(0xfffd);
1597                                         else if (tc == -3)
1598                                           tc = c;
1599 
1600                                         buf++; n++; count--;
1601                                         if (tc & ~console_charmask)
1602                                           continue; /* Conversion failed */
1603 
1604                                         *p++ = tc;
1605                                         *pos++ = tc | (attr << 8);
1606                                         ++putcs_count;
1607                                         ++nextx;
1608                                         if (nextx == cols || 
1609                                             putcs_count == sizeof (putcs_buf))
1610                                                 break;
1611                                 }
1612                                 
1613                                 sw->con_putcs(vc_cons[currcons].d,
1614                                               putcs_buf, putcs_count, y, x);
1615                                 if (nextx == cols) {
1616                                         pos--;
1617                                         x         = cols-1;
1618                                         need_wrap = decawm;
1619                                 } else
1620                                         x += putcs_count;
1621                                 continue;
1622                         }
1623                         
1624                         /* DPC: End of putcs support */
1625 #endif
1626                         
1627                         if (decim)
1628                                 insert_char(currcons);
1629                         *pos = (attr << 8) + tc;
1630                         if (currcons == fg_console)
1631                                 sw->con_putc(vc_cons[currcons].d,tc,y,x);
1632                         if (x == cols - 1)
1633                                 need_wrap = decawm;
1634                         else {
1635                                 pos++;
1636                                 x++;
1637                         }
1638                         continue;
1639                 }
1640 
1641                 /*
1642                  *  Control characters can be used in the _middle_
1643                  *  of an escape sequence.
1644                  */
1645                 switch (c) {
1646                     case 7:
1647                         if (bell_duration)
1648                             kd_mksound(bell_pitch, bell_duration);
1649                         continue;
1650                     case 8:
1651                         bs(currcons);
1652                         continue;
1653                     case 9:
1654                         pos -= x;
1655                         while (x < cols - 1) {
1656                                 x++;
1657                                 if (tab_stop[x >> 5] & (1 << (x & 31)))
1658                                         break;
1659                         }
1660                         pos += x;
1661                         continue;
1662                     case 10: case 11: case 12:
1663                         lf(currcons);
1664                         if (!is_kbd(lnm))
1665                                 continue;
1666                     case 13:
1667                         cr(currcons);
1668                         continue;
1669                         case 14:
1670                         charset = 1;
1671                         translate = set_translate(G1_charset);
1672                         disp_ctrl = 1;
1673                         continue;
1674                     case 15:
1675                         charset = 0;
1676                         translate = set_translate(G0_charset);
1677                         disp_ctrl = 0;
1678                         continue;
1679                     case 24: case 26:
1680                         vc_state = ESnormal;
1681                         continue;
1682                     case 27:
1683                         vc_state = ESesc;
1684                         continue;
1685                     case 127:
1686                         del(currcons);
1687                         continue;
1688                     case 128+27:
1689                         vc_state = ESsquare;
1690                         continue;
1691                 }
1692                 switch(vc_state) {
1693                     case ESesc:
1694                         vc_state = ESnormal;
1695                         switch (c) {
1696                             case '[':
1697                                 vc_state = ESsquare;
1698                                 continue;
1699                             case ']':
1700                                 vc_state = ESnonstd;
1701                                 continue;
1702                             case '%':
1703                                 vc_state = ESpercent;
1704                                 continue;
1705                             case 'E':
1706                                 cr(currcons);
1707                                 lf(currcons);
1708                                 continue;
1709                             case 'M':
1710                                 ri(currcons);
1711                                 continue;
1712                             case 'D':
1713                                 lf(currcons);
1714                                 continue;
1715                             case 'H':
1716                                 tab_stop[x >> 5] |= (1 << (x & 31));
1717                                 continue;
1718                             case 'Z':
1719                                 respond_ID(tty);
1720                                 continue;
1721                             case '7':
1722                                 save_cur(currcons);
1723                                 continue;
1724                             case '8':
1725                                 restore_cur(currcons);
1726                                 continue;
1727                             case '(':
1728                                 vc_state = ESsetG0;
1729                                 continue;
1730                             case ')':
1731                                 vc_state = ESsetG1;
1732                                 continue;
1733                             case '#':
1734                                 vc_state = EShash;
1735                                 continue;
1736                             case 'c':
1737                                 reset_terminal(currcons,1);
1738                                 continue;
1739                             case '>':  /* Numeric keypad */
1740                                 clr_kbd(kbdapplic);
1741                                 continue;
1742                             case '=':  /* Appl. keypad */
1743                                 set_kbd(kbdapplic);
1744                                 continue;
1745                         }       
1746                         continue;
1747                     case ESnonstd:
1748                         if (c=='P') {   /* palette escape sequence */
1749                             for (npar=0; npar<NPAR; npar++)
1750                                 par[npar] = 0 ;
1751                             npar = 0 ;
1752                             vc_state = ESpalette;
1753                             continue;
1754                         } else if (c=='R') {   /* reset palette */
1755 #if 0
1756                             reset_palette (currcons);
1757 #endif
1758                             vc_state = ESnormal;
1759                         } else
1760                             vc_state = ESnormal;
1761                         continue;
1762                 case ESpalette:
1763                         if ( (c>='0'&&c<='9') || (c>='A'&&c<='F') || (c>='a'&&c<='f') ) {
1764                             par[npar++] = (c>'9' ? (c&0xDF)-'A'+10 : c-'0') ;
1765                             if (npar==7) {
1766 #if 0
1767                                 int i = par[0]*3, j = 1;
1768                                 palette[i] = 16*par[j++];
1769                                 palette[i++] += par[j++];
1770                                 palette[i] = 16*par[j++];
1771                                 palette[i++] += par[j++];
1772                                 palette[i] = 16*par[j++];
1773                                 palette[i] += par[j];
1774                                 set_palette() ;
1775 #endif
1776                                 vc_state = ESnormal;
1777                             }
1778                         } else
1779                             vc_state = ESnormal;
1780                         continue;
1781                     case ESsquare:
1782                         for(npar = 0 ; npar < NPAR ; npar++)
1783                                 par[npar] = 0;
1784                         npar = 0;
1785                         vc_state = ESgetpars;
1786                         if (c == '[') { /* Function key */
1787                                 vc_state=ESfunckey;
1788                                 continue;
1789                         }
1790                         ques = (c=='?');
1791                         if (ques)
1792                                 continue;
1793                     case ESgetpars:
1794                         if (c==';' && npar<NPAR-1) {
1795                                 npar++;
1796                                 continue;
1797                         } else if (c>='0' && c<='9') {
1798                                 par[npar] *= 10;
1799                                 par[npar] += c-'0';
1800                                 continue;
1801                         } else vc_state=ESgotpars;
1802                     case ESgotpars:
1803                         vc_state = ESnormal;
1804                         switch(c) {
1805                             case 'h':
1806                                 set_mode(currcons,1);
1807                                 continue;
1808                             case 'l':
1809                                 set_mode(currcons,0);
1810                                 continue;
1811                             case 'n':
1812                                 if (!ques)
1813                                         if (par[0] == 5)
1814                                                 status_report(tty);
1815                                         else if (par[0] == 6)
1816                                                 cursor_report(currcons,tty);
1817                                 continue;
1818                         }
1819                         if (ques) {
1820                                 ques = 0;
1821                                 continue;
1822                         }
1823                         switch(c) {
1824                             case 'G': case '`':
1825                                 if (par[0]) par[0]--;
1826                                 gotoxy(currcons,par[0],y);
1827                                 continue;
1828                             case 'A':
1829                                 if (!par[0]) par[0]++;
1830                                 gotoxy(currcons,x,y-par[0]);
1831                                 continue;
1832                             case 'B': case 'e':
1833                                 if (!par[0]) par[0]++;
1834                                 gotoxy(currcons,x,y+par[0]);
1835                                 continue;
1836                             case 'C': case 'a':
1837                                 if (!par[0]) par[0]++;
1838                                 gotoxy(currcons,x+par[0],y);
1839                                 continue;
1840                             case 'D':
1841                                 if (!par[0]) par[0]++;
1842                                 gotoxy(currcons,x-par[0],y);
1843                                 continue;
1844                             case 'E':
1845                                 if (!par[0]) par[0]++;
1846                                 gotoxy(currcons,0,y+par[0]);
1847                                 continue;
1848                             case 'F':
1849                                 if (!par[0]) par[0]++;
1850                                 gotoxy(currcons,0,y-par[0]);
1851                                 continue;
1852                             case 'd':
1853                                 if (par[0]) par[0]--;
1854                                 gotoxy(currcons,x,par[0]);
1855                                 continue;
1856                             case 'H': case 'f':
1857                                 if (par[0]) par[0]--;
1858                                 if (par[1]) par[1]--;
1859                                 gotoxy(currcons,par[1],par[0]);
1860                                 continue;
1861                             case 'J':
1862                                 csi_J(currcons,par[0]);
1863                                 continue;
1864                             case 'K':
1865                                 csi_K(currcons,par[0]);
1866                                 continue;
1867                             case 'L':
1868                                 csi_L(currcons,par[0]);
1869                                 continue;
1870                             case 'M':
1871                                 csi_M(currcons,par[0]);
1872                                 continue;
1873                             case 'P':
1874                                 csi_P(currcons,par[0]);
1875                                 continue;
1876                             case 'c':
1877                                 if (!par[0])
1878                                         respond_ID(tty);
1879                                 continue;
1880                             case 'g':
1881                                 if (!par[0])
1882                                         tab_stop[x >> 5] &= ~(1 << (x & 31));
1883                                 else if (par[0] == 3) {
1884                                         tab_stop[0] =
1885                                                 tab_stop[1] =
1886                                                         tab_stop[2] =
1887                                                                 tab_stop[3] =
1888                                                                         tab_stop[4] = 0;
1889                                 }
1890                                 continue;
1891                             case 'm':
1892                                 csi_m(currcons);
1893                                 continue;
1894                             case 'q': /* DECLL - but only 3 leds */
1895                                 /* map 0,1,2,3 to 0,1,2,4 */
1896                                 if (par[0] < 4)
1897                                         setledstate(kbd_table + currcons,
1898                                                     (par[0] < 3) ? par[0] : 4);
1899                                 continue;
1900                             case 'r':
1901                                 if (!par[0])
1902                                         par[0]++;
1903                                 if (!par[1])
1904                                         par[1] = rows;
1905                                 /* Minimum allowed region is 2 lines */
1906                                 if (par[0] < par[1] &&
1907                                     par[1] <= rows) {
1908                                         top=par[0]-1;
1909                                         bottom=par[1];
1910                                         gotoxy(currcons,0,0);
1911                                 }
1912                                 continue;
1913                             case 's':
1914                                 save_cur(currcons);
1915                                 continue;
1916                             case 'u':
1917                                 restore_cur(currcons);
1918                                 continue;
1919                             case 'X':
1920                                 csi_X(currcons, par[0]);
1921                                 continue;
1922                             case '@':
1923                                 csi_at(currcons,par[0]);
1924                                 continue;
1925                             case ']': /* setterm functions */
1926                                 setterm_command(currcons);
1927                                 continue;
1928                         }
1929                         continue;
1930                     case ESpercent:
1931                         vc_state = ESnormal;
1932                         switch (c) {
1933                             case '@':  /* defined in ISO 2022 */
1934                                 utf = 0;
1935                                 continue;
1936                             case 'G':  /* prelim official escape code */
1937                             case '8':  /* retained for compatibility */
1938                                 utf = 1;
1939                                 continue;
1940                         }
1941                         continue;
1942                     case ESfunckey:
1943                         vc_state = ESnormal;
1944                         continue;
1945                     case EShash:
1946                         vc_state = ESnormal;
1947                         if (c == '8') {
1948                                 /* DEC screen alignment test. kludge :-) */
1949                                 video_erase_char =
1950                                         (video_erase_char & 0xff00) | 'E';
1951                                 /* Arno:
1952                                  * Doesn't work, because csi_J(c,2)
1953                                  * calls con_clear and doesn't print
1954                                  * the erase char..
1955                                  */
1956                                 csi_J(currcons, 2);
1957                                 video_erase_char =
1958                                         (video_erase_char & 0xff00) | ' ';
1959                         }
1960                         continue;
1961                     case ESsetG0:
1962                         if (c == '0')
1963                                 G0_charset = GRAF_MAP;
1964                         else if (c == 'B')
1965                                 G0_charset = LAT1_MAP;
1966                         else if (c == 'U')
1967                                 G0_charset = IBMPC_MAP;
1968                         else if (c == 'K')
1969                                 G0_charset = USER_MAP;
1970                         if (charset == 0)
1971                                 translate = set_translate(G0_charset);
1972                         vc_state = ESnormal;
1973                         continue;
1974                     case ESsetG1:
1975                         if (c == '0')
1976                                 G1_charset = GRAF_MAP;
1977                         else if (c == 'B')
1978                                 G1_charset = LAT1_MAP;
1979                         else if (c == 'U')
1980                                 G1_charset = IBMPC_MAP;
1981                         else if (c == 'K')
1982                                 G1_charset = USER_MAP;
1983                         if (charset == 1)
1984                                 translate = set_translate(G1_charset);
1985                         vc_state = ESnormal;
1986                         continue;
1987                     default:
1988                         vc_state = ESnormal;
1989                 }
1990         }
1991         if (vcmode != KD_GRAPHICS)
1992                 set_cursor(currcons);
1993         enable_bh(CONSOLE_BH);
1994         return n;
1995 }
1996 
1997 static int con_write_room(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
1998 {
1999         if (tty->stopped)
2000                 return 0;
2001         return 4096;            /* No limit, really; we're not buffering */
2002 }
2003 
2004 static int con_chars_in_buffer(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
2005 {
2006         return 0;               /* we're not buffering */
2007 }
2008 
2009 void poke_blanked_console(void)
     /* [previous][next][first][last][top][bottom][index][help] */
2010 {
2011         timer_active &= ~(1<<BLANK_TIMER);
2012         if (vt_cons[fg_console]->vc_mode == KD_GRAPHICS)
2013                 return;
2014         if (console_blanked) {
2015                 timer_table[BLANK_TIMER].fn = unblank_screen;
2016                 timer_table[BLANK_TIMER].expires = 0;
2017                 timer_active |= 1<<BLANK_TIMER;
2018         } else if (blankinterval) {
2019                 timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
2020                 timer_active |= 1<<BLANK_TIMER;
2021         }
2022 }
2023 
2024 /* DPC: New version of console_print using putcs */
2025 
2026 void console_print(const char * b)
     /* [previous][next][first][last][top][bottom][index][help] */
2027 {
2028    int currcons = fg_console;
2029    unsigned char c;
2030    const char *start = b;
2031    ushort count      = 0;
2032    ushort myx        = x;
2033    static int printing = 0;
2034 
2035    if (!printable || printing)
2036            return;       /* console not yet initialized */
2037    printing = 1;
2038 
2039    if (kmsg_redirect && vc_cons_allocated(kmsg_redirect - 1))
2040            currcons = kmsg_redirect - 1;
2041 
2042    if (!vc_cons_allocated(currcons)) {
2043            /* impossible */
2044            printk("console_print: tty %d not allocated ??\n", currcons+1);
2045            printing = 0;
2046            return;
2047    }
2048 
2049    /* undraw cursor first */
2050    hide_cursor(currcons);
2051 
2052    /* Contrived structure to try and emulate original need_wrap behaviour
2053     * Problems caused when we have need_wrap set on '\n' character */
2054    
2055    while ((c = *(b++)) != 0) {
2056        if (c == 10 || c == 13 || c == 8 || need_wrap) {
2057            if ((count = b - start - 1) > 0) {
2058                sw->con_putcs(vc_cons[currcons].d, start, count ,
2059                              y, x);
2060                x += count;
2061                if (need_wrap)
2062                  x--;
2063            }
2064 
2065            if (c == 8) {        /* backspace */
2066                bs(currcons);
2067                start = b;
2068                myx = x;
2069                continue;
2070            }
2071            if (c != 13)
2072                lf(currcons);
2073            cr(currcons);
2074 
2075            if (c == 10 || c == 13) {
2076                start = b; myx = x; continue;
2077            }
2078 
2079            start = b-1; myx = x;
2080        }
2081 
2082        *pos = c | (attr << 8);
2083        if (myx == cols - 1) {
2084            need_wrap = 1;
2085            continue;
2086        }
2087        pos++;
2088        myx++;
2089    }
2090 
2091    if ((count = b - start -1) > 0) {
2092        sw->con_putcs(vc_cons[currcons].d, start, count ,
2093                      y, x);
2094        x += count;
2095        if (x == cols)
2096          {
2097            x--;
2098            need_wrap = 1;
2099          }
2100    }
2101    
2102    set_cursor(currcons);
2103    poke_blanked_console();
2104    printing = 0;
2105 }
2106 
2107 
2108 /*
2109  * con_throttle and con_unthrottle are only used for
2110  * paste_selection(), which has to stuff in a large number of
2111  * characters...
2112  */
2113 static void con_throttle(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
2114 {
2115 }
2116 
2117 static void con_unthrottle(struct tty_struct *tty)
     /* [previous][next][first][last][top][bottom][index][help] */
2118 {
2119         struct vt_struct *vt = (struct vt_struct *) tty->driver_data;
2120 
2121         wake_up_interruptible(&vt->paste_wait);
2122 }
2123 
2124 static void vc_init(unsigned int currcons, int do_clear)
     /* [previous][next][first][last][top][bottom][index][help] */
2125 {
2126         long base = (long) vc_scrbuf[currcons];
2127 
2128         pos = (unsigned short *)(origin = (ulong)video_mem_start = base);
2129         scr_end = base + screenbuf_size;
2130         video_mem_end = base + screenbuf_size;
2131         reset_vc(currcons);
2132         def_color       = 0x07;   /* white */
2133         ulcolor         = 0x0f;   /* bold white */
2134         halfcolor       = 0x08;   /* grey */
2135         vt_cons[currcons]->paste_wait = 0;
2136         reset_terminal(currcons, do_clear);
2137 }
2138 
2139 /*
2140  * This is the console switching bottom half handler.
2141  *
2142  * Doing console switching in a bottom half handler allows
2143  * us to do the switches asynchronously (needed when we want
2144  * to switch due to a keyboard interrupt), while still giving
2145  * us the option to easily disable it to avoid races when we
2146  * need to write to the console.
2147  */
2148 static void console_bh(void)
     /* [previous][next][first][last][top][bottom][index][help] */
2149 {
2150         if (want_console >= 0) {
2151                 if (want_console != fg_console) {
2152                         change_console(want_console);
2153                         /* we only changed when the console had already
2154                            been allocated - a new console is not created
2155                            in an interrupt routine */
2156                 }
2157                 want_console = -1;
2158         }
2159         if (do_poke_blanked_console) { /* do not unblank for a LED change */
2160                 do_poke_blanked_console = 0;
2161                 poke_blanked_console();
2162         }
2163 }
2164 
2165 /*
2166  *  unsigned long con_init(unsigned long);
2167  *
2168  * This routine initializes console interrupts, and does nothing
2169  * else. If you want the screen to clear, call tty_write with
2170  * the appropriate escape-sequence.
2171  *
2172  * Reads the information preserved by setup.s to determine the current display
2173  * type and sets everything accordingly.
2174  */
2175 unsigned long con_init(unsigned long kmem_start)
     /* [previous][next][first][last][top][bottom][index][help] */
2176 {
2177         char *display_desc = "????";
2178         unsigned int currcons = 0;
2179         extern int serial_debug;
2180 
2181         memset(&console_driver, 0, sizeof(struct tty_driver));
2182         console_driver.magic = TTY_DRIVER_MAGIC;
2183         console_driver.name = "tty";
2184         console_driver.name_base = 1;
2185         console_driver.major = TTY_MAJOR;
2186         console_driver.minor_start = 1;
2187         console_driver.num = MAX_NR_CONSOLES;
2188         console_driver.type = TTY_DRIVER_TYPE_CONSOLE;
2189         console_driver.init_termios = tty_std_termios;
2190         console_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS;
2191         console_driver.refcount = &console_refcount;
2192         console_driver.table = console_table;
2193         console_driver.termios = console_termios;
2194         console_driver.termios_locked = console_termios_locked;
2195 
2196         console_driver.open = con_open;
2197         console_driver.write = con_write;
2198         console_driver.write_room = con_write_room;
2199         console_driver.chars_in_buffer = con_chars_in_buffer;
2200         console_driver.ioctl = vt_ioctl;
2201         console_driver.stop = con_stop;
2202         console_driver.start = con_start;
2203         console_driver.throttle = con_throttle;
2204         console_driver.unthrottle = con_unthrottle;
2205         
2206         if (tty_register_driver(&console_driver))
2207                 panic("Couldn't register console driver\n");
2208         
2209         kmem_start = conswitchp->con_startup (kmem_start, &display_desc);
2210 
2211         timer_table[BLANK_TIMER].fn = blank_screen;
2212         timer_table[BLANK_TIMER].expires = 0;
2213         if (blankinterval) {
2214                 timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
2215                 timer_active |= 1<<BLANK_TIMER;
2216         }
2217 
2218         /* Due to kmalloc roundup allocating statically is more efficient -
2219            so provide MIN_NR_CONSOLES for people with very little memory */
2220         for (currcons = 0; currcons < MIN_NR_CONSOLES; currcons++) {
2221                 vc_cons[currcons].d = (struct vc_data *) kmem_start;
2222                 kmem_start += sizeof(struct vc_data);
2223                 vt_cons[currcons] = (struct vt_struct *) kmem_start;
2224                 kmem_start += sizeof(struct vt_struct);
2225 
2226                 /* ++Geert: sw->con_init determines console size */
2227                 sw = conswitchp;
2228                 cons_num = currcons;
2229                 sw->con_init (vc_cons[currcons].d);
2230                 size_row = cols<<1;
2231                 screenbuf_size = rows*size_row;
2232 
2233                 vc_scrbuf[currcons] = (unsigned short *) kmem_start;
2234                 kmem_start += screenbuf_size;
2235                 kmalloced = 0;
2236                 vc_init(currcons, currcons);
2237         }
2238 
2239         currcons = fg_console = 0;
2240 
2241         gotoxy(currcons,0,0);
2242         csi_J(currcons, 0);
2243         printable = 1;
2244         update_screen(fg_console);
2245         sw->con_cursor(vc_cons[currcons].d, CM_DRAW);
2246         printable = 1;
2247 
2248         /* If "serdebug" cmd line option was present, don't register for printk */
2249         if (!serial_debug)
2250                 register_console(console_print);
2251         printk("Console: %s %s %ldx%ld, %d virtual console%s (max %d)\n",
2252                 can_do_color ? "colour":"mono",
2253                 display_desc,
2254                 cols,rows,
2255                 MIN_NR_CONSOLES, (MIN_NR_CONSOLES == 1) ? "" : "s", MAX_NR_CONSOLES);
2256 
2257         init_bh(CONSOLE_BH, console_bh);
2258         return kmem_start;
2259 }
2260 
2261 void do_blank_screen(int nopowersave)
     /* [previous][next][first][last][top][bottom][index][help] */
2262 {
2263         int currcons;
2264 
2265         if (console_blanked)
2266                 return;
2267 
2268         if (!vc_cons_allocated(fg_console)) {
2269                 /* impossible */
2270                 printk("blank_screen: tty %d not allocated ??\n", fg_console+1);
2271                 return;
2272         }
2273 
2274         /* don't blank graphics */
2275         if (vt_cons[fg_console]->vc_mode == KD_TEXT) {
2276                 timer_active &= ~(1<<BLANK_TIMER);
2277                 timer_table[BLANK_TIMER].fn = unblank_screen;
2278 
2279                 /* try not to lose information by blanking,
2280                    and not to waste memory */
2281                 currcons = fg_console;
2282                 has_scrolled = 0;
2283                 sw->con_blank (1);
2284         }
2285         else
2286                 hide_cursor(fg_console);
2287         console_blanked = fg_console + 1;
2288 }
2289 
2290 void do_unblank_screen(void)
     /* [previous][next][first][last][top][bottom][index][help] */
2291 {
2292         int currcons;
2293 
2294         if (!console_blanked)
2295                 return;
2296         if (!vc_cons_allocated(fg_console)) {
2297                 /* impossible */
2298                 printk("unblank_screen: tty %d not allocated ??\n", fg_console+1);
2299                 return;
2300         }
2301         timer_table[BLANK_TIMER].fn = blank_screen;
2302         if (blankinterval) {
2303                 timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
2304                 timer_active |= 1<<BLANK_TIMER;
2305         }
2306 
2307         currcons = fg_console;
2308         console_blanked = 0;
2309         if (sw->con_blank (0))
2310                 /* Low-level driver cannot restore -> do it ourselves */
2311                 update_screen( fg_console );
2312         set_cursor (fg_console);
2313 }
2314 
2315 void update_screen(int new_console)
     /* [previous][next][first][last][top][bottom][index][help] */
2316 {
2317         int currcons = fg_console;
2318         int xx, yy, startx, attr_save;
2319         char buf[256], *bufp;
2320         unsigned short *p;
2321         static int lock = 0;
2322 
2323         if (/* new_console == fg_console || */ lock)
2324                 return;
2325         if (!vc_cons_allocated(new_console)) {
2326                 /* strange ... */
2327                 printk("update_screen: tty %d not allocated ??\n", new_console+1);
2328                 return;
2329         }
2330         lock = 1;
2331 
2332         clear_selection();
2333 
2334         currcons = fg_console = new_console;
2335         sw->con_cursor (vc_cons[currcons].d, CM_ERASE);
2336         sw->con_switch (vc_cons[new_console].d);
2337         /* Update the screen contents */
2338         p = video_mem_start;
2339         attr_save = attr;
2340         for (yy = 0; yy < rows; yy++)
2341           {
2342             bufp = buf;
2343             for (startx = xx = 0; xx < cols; xx++)
2344               {
2345                 if (attr != ((*p >> 8) & 0xff))
2346                   {
2347                     if (bufp > buf)
2348                       sw->con_putcs (vc_cons[currcons].d, buf, bufp - buf,
2349                                      yy, startx);
2350                     startx = xx;
2351                     bufp = buf;
2352                     attr = (*p >> 8) & 0xff;
2353                   }
2354                 *bufp++ = *p++;
2355                 if (bufp == buf + sizeof (buf))
2356                   {
2357                     sw->con_putcs (vc_cons[currcons].d, buf, bufp - buf,
2358                                    yy, startx);
2359                     startx = xx + 1;
2360                     bufp = buf;
2361                   }
2362               }
2363             if (bufp > buf)
2364               sw->con_putcs (vc_cons[currcons].d, buf, bufp - buf,
2365                              yy, startx);
2366           }
2367         set_cursor (currcons);
2368         attr = attr_save;
2369         set_leds();
2370         compute_shiftstate();
2371         lock = 0;
2372 }
2373 
2374 /*
2375  * If a blank_screen is due to a timer, then a power save is allowed.
2376  * If it is related to console_switching, then avoid vesa_blank().
2377  */
2378 static void blank_screen(void)
     /* [previous][next][first][last][top][bottom][index][help] */
2379 {
2380         do_blank_screen(0);
2381 }
2382 
2383 static void unblank_screen(void)
     /* [previous][next][first][last][top][bottom][index][help] */
2384 {
2385         do_unblank_screen();
2386 }
2387 
2388 /*
2389  * Allocate the console screen memory.
2390  */
2391 int con_open(struct tty_struct *tty, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
2392 {
2393         unsigned int currcons;
2394         int i;
2395 
2396         currcons = MINOR(tty->device) - tty->driver.minor_start;
2397         
2398         i = vc_allocate(currcons);
2399         if (i)
2400                 return i;
2401 
2402         vt_cons[currcons]->vc_num = currcons;
2403         tty->driver_data = vt_cons[currcons];
2404         
2405         if (!tty->winsize.ws_row && !tty->winsize.ws_col) {
2406                 tty->winsize.ws_row = rows;
2407                 tty->winsize.ws_col = cols;
2408         }
2409 
2410         return 0;
2411 }
2412 
2413 /*
2414  * PIO_FONT support.
2415  *
2416  * The font loading code goes back to the codepage package by
2417  * Joel Hoffman (joel@wam.umd.edu). (He reports that the original
2418  * reference is: "From: p. 307 of _Programmer's Guide to PC & PS/2
2419  * Video Systems_ by Richard Wilton. 1987.  Microsoft Press".)
2420  *
2421  * Change for certain monochrome monitors by Yury Shevchuck
2422  * (sizif@botik.yaroslavl.su).
2423  */
2424 
2425 #define colourmap ((char *)0xa0000)
2426 /* Pauline Middelink <middelin@polyware.iaf.nl> reports that we
2427    should use 0xA0000 for the bwmap as well.. */
2428 #define blackwmap ((char *)0xa0000)
2429 #define cmapsz 8192
2430 #define seq_port_reg (0x3c4)
2431 #define seq_port_val (0x3c5)
2432 #define gr_port_reg (0x3ce)
2433 #define gr_port_val (0x3cf)
2434 
2435 static int set_get_font(char * arg, int set)
     /* [previous][next][first][last][top][bottom][index][help] */
2436 {
2437 #ifdef CAN_LOAD_EGA_FONTS
2438         int i;
2439         char *charmap;
2440         int beg;
2441 
2442         /* no use to "load" CGA... */
2443 
2444         if (video_type == VIDEO_TYPE_EGAC) {
2445                 charmap = colourmap;
2446                 beg = 0x0e;
2447         } else if (video_type == VIDEO_TYPE_EGAM) {
2448                 charmap = blackwmap;
2449                 beg = 0x0a;
2450         } else
2451                 return -EINVAL;
2452 
2453         i = verify_area(set ? VERIFY_READ : VERIFY_WRITE, (void *)arg, cmapsz);
2454         if (i)
2455                 return i;
2456 
2457         cli();
2458         outb_p( 0x00, seq_port_reg );   /* First, the sequencer */
2459         outb_p( 0x01, seq_port_val );   /* Synchronous reset */
2460         outb_p( 0x02, seq_port_reg );
2461         outb_p( 0x04, seq_port_val );   /* CPU writes only to map 2 */
2462         outb_p( 0x04, seq_port_reg );
2463         outb_p( 0x07, seq_port_val );   /* Sequential addressing */
2464         outb_p( 0x00, seq_port_reg );
2465         outb_p( 0x03, seq_port_val );   /* Clear synchronous reset */
2466 
2467         outb_p( 0x04, gr_port_reg );    /* Now, the graphics controller */
2468         outb_p( 0x02, gr_port_val );    /* select map 2 */
2469         outb_p( 0x05, gr_port_reg );
2470         outb_p( 0x00, gr_port_val );    /* disable odd-even addressing */
2471         outb_p( 0x06, gr_port_reg );
2472         outb_p( 0x00, gr_port_val );    /* map start at A000:0000 */
2473         sti();
2474 
2475         if (set)
2476                 memcpy_fromfs (charmap, arg, cmapsz);
2477         else
2478                 memcpy_tofs (arg, charmap, cmapsz);
2479 
2480         cli();
2481         outb_p( 0x00, seq_port_reg );   /* First, the sequencer */
2482         outb_p( 0x01, seq_port_val );   /* Synchronous reset */
2483         outb_p( 0x02, seq_port_reg );
2484         outb_p( 0x03, seq_port_val );   /* CPU writes to maps 0 and 1 */
2485         outb_p( 0x04, seq_port_reg );
2486         outb_p( 0x03, seq_port_val );   /* odd-even addressing */
2487         outb_p( 0x00, seq_port_reg );
2488         outb_p( 0x03, seq_port_val );   /* clear synchronous reset */
2489 
2490         outb_p( 0x04, gr_port_reg );    /* Now, the graphics controller */
2491         outb_p( 0x00, gr_port_val );    /* select map 0 for CPU */
2492         outb_p( 0x05, gr_port_reg );
2493         outb_p( 0x10, gr_port_val );    /* enable even-odd addressing */
2494         outb_p( 0x06, gr_port_reg );
2495         outb_p( beg, gr_port_val );     /* map starts at b800:0 or b000:0 */
2496         sti();
2497 
2498         return 0;
2499 #else
2500         return -EINVAL;
2501 #endif
2502 }
2503 
2504 /*
2505  * Load palette into the EGA/VGA DAC registers. arg points to a colour
2506  * map, 3 bytes per colour, 16 colours, range from 0 to 255.
2507  */
2508 
2509 int con_set_cmap (unsigned char *arg)
     /* [previous][next][first][last][top][bottom][index][help] */
2510 {
2511         return -EINVAL;
2512 }
2513 
2514 int con_get_cmap (unsigned char *arg)
     /* [previous][next][first][last][top][bottom][index][help] */
2515 {
2516         return -EINVAL;
2517 }
2518 
2519 void reset_palette(int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
2520 {
2521 }
2522 
2523 void set_palette(void)
     /* [previous][next][first][last][top][bottom][index][help] */
2524 {
2525 }
2526 
2527 /*
2528  * Load font into the EGA/VGA character generator. arg points to a 8192
2529  * byte map, 32 bytes per character. Only first H of them are used for
2530  * 8xH fonts (0 < H <= 32).
2531  */
2532 
2533 int con_set_font (char *arg)
     /* [previous][next][first][last][top][bottom][index][help] */
2534 {
2535         hashtable_contents_valid = 0;
2536         return set_get_font (arg,1);
2537 }
2538 
2539 int con_get_font (char *arg)
     /* [previous][next][first][last][top][bottom][index][help] */
2540 {
2541         return set_get_font (arg,0);
2542 }
2543 
2544 /*
2545  * Adjust the screen to fit a font of a certain height
2546  *
2547  * Returns < 0 for error, 0 if nothing changed, and the number
2548  * of lines on the adjusted console if changed.
2549  */
2550 int con_adjust_height(unsigned long fontheight)
     /* [previous][next][first][last][top][bottom][index][help] */
2551 {
2552         return -EINVAL;
2553 }
2554 
2555 void set_vesa_blanking(int arg)
     /* [previous][next][first][last][top][bottom][index][help] */
2556 {
2557 }
2558 
2559 unsigned long get_video_num_lines(unsigned int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
2560 {
2561         return(rows);
2562 }
2563 
2564 unsigned long get_video_num_columns(unsigned int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
2565 {
2566         return(cols);
2567 }
2568 
2569 unsigned long get_video_size_row(unsigned int currcons)
     /* [previous][next][first][last][top][bottom][index][help] */
2570 {
2571         return(size_row);
2572 }

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