PageRenderTime 138ms CodeModel.GetById 13ms app.highlight 109ms RepoModel.GetById 1ms app.codeStats 1ms

/drivers/char/vt.c

https://bitbucket.org/evzijst/gittest
C | 3242 lines | 2506 code | 325 blank | 411 comment | 557 complexity | ddebc660296223b98d318d177e610f5f MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/*
   2 *  linux/drivers/char/vt.c
   3 *
   4 *  Copyright (C) 1991, 1992  Linus Torvalds
   5 */
   6
   7/*
   8 * Hopefully this will be a rather complete VT102 implementation.
   9 *
  10 * Beeping thanks to John T Kohl.
  11 *
  12 * Virtual Consoles, Screen Blanking, Screen Dumping, Color, Graphics
  13 *   Chars, and VT100 enhancements by Peter MacDonald.
  14 *
  15 * Copy and paste function by Andrew Haylett,
  16 *   some enhancements by Alessandro Rubini.
  17 *
  18 * Code to check for different video-cards mostly by Galen Hunt,
  19 * <g-hunt@ee.utah.edu>
  20 *
  21 * Rudimentary ISO 10646/Unicode/UTF-8 character set support by
  22 * Markus Kuhn, <mskuhn@immd4.informatik.uni-erlangen.de>.
  23 *
  24 * Dynamic allocation of consoles, aeb@cwi.nl, May 1994
  25 * Resizing of consoles, aeb, 940926
  26 *
  27 * Code for xterm like mouse click reporting by Peter Orbaek 20-Jul-94
  28 * <poe@daimi.aau.dk>
  29 *
  30 * User-defined bell sound, new setterm control sequences and printk
  31 * redirection by Martin Mares <mj@k332.feld.cvut.cz> 19-Nov-95
  32 *
  33 * APM screenblank bug fixed Takashi Manabe <manabe@roy.dsl.tutics.tut.jp>
  34 *
  35 * Merge with the abstract console driver by Geert Uytterhoeven
  36 * <geert@linux-m68k.org>, Jan 1997.
  37 *
  38 *   Original m68k console driver modifications by
  39 *
  40 *     - Arno Griffioen <arno@usn.nl>
  41 *     - David Carter <carter@cs.bris.ac.uk>
  42 * 
  43 *   The abstract console driver provides a generic interface for a text
  44 *   console. It supports VGA text mode, frame buffer based graphical consoles
  45 *   and special graphics processors that are only accessible through some
  46 *   registers (e.g. a TMS340x0 GSP).
  47 *
  48 *   The interface to the hardware is specified using a special structure
  49 *   (struct consw) which contains function pointers to console operations
  50 *   (see <linux/console.h> for more information).
  51 *
  52 * Support for changeable cursor shape
  53 * by Pavel Machek <pavel@atrey.karlin.mff.cuni.cz>, August 1997
  54 *
  55 * Ported to i386 and con_scrolldelta fixed
  56 * by Emmanuel Marty <core@ggi-project.org>, April 1998
  57 *
  58 * Resurrected character buffers in videoram plus lots of other trickery
  59 * by Martin Mares <mj@atrey.karlin.mff.cuni.cz>, July 1998
  60 *
  61 * Removed old-style timers, introduced console_timer, made timer
  62 * deletion SMP-safe.  17Jun00, Andrew Morton <andrewm@uow.edu.au>
  63 *
  64 * Removed console_lock, enabled interrupts across all console operations
  65 * 13 March 2001, Andrew Morton
  66 */
  67
  68#include <linux/module.h>
  69#include <linux/types.h>
  70#include <linux/sched.h>
  71#include <linux/tty.h>
  72#include <linux/tty_flip.h>
  73#include <linux/kernel.h>
  74#include <linux/string.h>
  75#include <linux/errno.h>
  76#include <linux/kd.h>
  77#include <linux/slab.h>
  78#include <linux/major.h>
  79#include <linux/mm.h>
  80#include <linux/console.h>
  81#include <linux/init.h>
  82#include <linux/devfs_fs_kernel.h>
  83#include <linux/vt_kern.h>
  84#include <linux/selection.h>
  85#include <linux/tiocl.h>
  86#include <linux/kbd_kern.h>
  87#include <linux/consolemap.h>
  88#include <linux/timer.h>
  89#include <linux/interrupt.h>
  90#include <linux/config.h>
  91#include <linux/workqueue.h>
  92#include <linux/bootmem.h>
  93#include <linux/pm.h>
  94#include <linux/font.h>
  95#include <linux/bitops.h>
  96
  97#include <asm/io.h>
  98#include <asm/system.h>
  99#include <asm/uaccess.h>
 100
 101
 102const struct consw *conswitchp;
 103
 104/* A bitmap for codes <32. A bit of 1 indicates that the code
 105 * corresponding to that bit number invokes some special action
 106 * (such as cursor movement) and should not be displayed as a
 107 * glyph unless the disp_ctrl mode is explicitly enabled.
 108 */
 109#define CTRL_ACTION 0x0d00ff81
 110#define CTRL_ALWAYS 0x0800f501	/* Cannot be overridden by disp_ctrl */
 111
 112/*
 113 * Here is the default bell parameters: 750HZ, 1/8th of a second
 114 */
 115#define DEFAULT_BELL_PITCH	750
 116#define DEFAULT_BELL_DURATION	(HZ/8)
 117
 118extern void vcs_make_devfs(struct tty_struct *tty);
 119extern void vcs_remove_devfs(struct tty_struct *tty);
 120
 121extern void console_map_init(void);
 122#ifdef CONFIG_PROM_CONSOLE
 123extern void prom_con_init(void);
 124#endif
 125#ifdef CONFIG_MDA_CONSOLE
 126extern int mda_console_init(void);
 127#endif
 128
 129struct vc vc_cons [MAX_NR_CONSOLES];
 130
 131#ifndef VT_SINGLE_DRIVER
 132static const struct consw *con_driver_map[MAX_NR_CONSOLES];
 133#endif
 134
 135static int con_open(struct tty_struct *, struct file *);
 136static void vc_init(struct vc_data *vc, unsigned int rows,
 137		    unsigned int cols, int do_clear);
 138static void gotoxy(struct vc_data *vc, int new_x, int new_y);
 139static void save_cur(struct vc_data *vc);
 140static void reset_terminal(struct vc_data *vc, int do_clear);
 141static void con_flush_chars(struct tty_struct *tty);
 142static void set_vesa_blanking(char __user *p);
 143static void set_cursor(struct vc_data *vc);
 144static void hide_cursor(struct vc_data *vc);
 145static void console_callback(void *ignored);
 146static void blank_screen_t(unsigned long dummy);
 147static void set_palette(struct vc_data *vc);
 148
 149static int printable;		/* Is console ready for printing? */
 150
 151/*
 152 * ignore_poke: don't unblank the screen when things are typed.  This is
 153 * mainly for the privacy of braille terminal users.
 154 */
 155static int ignore_poke;
 156
 157int do_poke_blanked_console;
 158int console_blanked;
 159
 160static int vesa_blank_mode; /* 0:none 1:suspendV 2:suspendH 3:powerdown */
 161static int blankinterval = 10*60*HZ;
 162static int vesa_off_interval;
 163
 164static DECLARE_WORK(console_work, console_callback, NULL);
 165
 166/*
 167 * fg_console is the current virtual console,
 168 * last_console is the last used one,
 169 * want_console is the console we want to switch to,
 170 * kmsg_redirect is the console for kernel messages,
 171 */
 172int fg_console;
 173int last_console;
 174int want_console = -1;
 175int kmsg_redirect;
 176
 177/*
 178 * For each existing display, we have a pointer to console currently visible
 179 * on that display, allowing consoles other than fg_console to be refreshed
 180 * appropriately. Unless the low-level driver supplies its own display_fg
 181 * variable, we use this one for the "master display".
 182 */
 183static struct vc_data *master_display_fg;
 184
 185/*
 186 * Unfortunately, we need to delay tty echo when we're currently writing to the
 187 * console since the code is (and always was) not re-entrant, so we schedule
 188 * all flip requests to process context with schedule-task() and run it from
 189 * console_callback().
 190 */
 191
 192/*
 193 * For the same reason, we defer scrollback to the console callback.
 194 */
 195static int scrollback_delta;
 196
 197/*
 198 * Hook so that the power management routines can (un)blank
 199 * the console on our behalf.
 200 */
 201int (*console_blank_hook)(int);
 202
 203static struct timer_list console_timer;
 204static int blank_state;
 205static int blank_timer_expired;
 206enum {
 207	blank_off = 0,
 208	blank_normal_wait,
 209	blank_vesa_wait,
 210};
 211
 212/*
 213 *	Low-Level Functions
 214 */
 215
 216#define IS_FG(vc)	((vc)->vc_num == fg_console)
 217
 218#ifdef VT_BUF_VRAM_ONLY
 219#define DO_UPDATE(vc)	0
 220#else
 221#define DO_UPDATE(vc)	CON_IS_VISIBLE(vc)
 222#endif
 223
 224static inline unsigned short *screenpos(struct vc_data *vc, int offset, int viewed)
 225{
 226	unsigned short *p;
 227	
 228	if (!viewed)
 229		p = (unsigned short *)(vc->vc_origin + offset);
 230	else if (!vc->vc_sw->con_screen_pos)
 231		p = (unsigned short *)(vc->vc_visible_origin + offset);
 232	else
 233		p = vc->vc_sw->con_screen_pos(vc, offset);
 234	return p;
 235}
 236
 237static inline void scrolldelta(int lines)
 238{
 239	scrollback_delta += lines;
 240	schedule_console_callback();
 241}
 242
 243void schedule_console_callback(void)
 244{
 245	schedule_work(&console_work);
 246}
 247
 248static void scrup(struct vc_data *vc, unsigned int t, unsigned int b, int nr)
 249{
 250	unsigned short *d, *s;
 251
 252	if (t+nr >= b)
 253		nr = b - t - 1;
 254	if (b > vc->vc_rows || t >= b || nr < 1)
 255		return;
 256	if (CON_IS_VISIBLE(vc) && vc->vc_sw->con_scroll(vc, t, b, SM_UP, nr))
 257		return;
 258	d = (unsigned short *)(vc->vc_origin + vc->vc_size_row * t);
 259	s = (unsigned short *)(vc->vc_origin + vc->vc_size_row * (t + nr));
 260	scr_memmovew(d, s, (b - t - nr) * vc->vc_size_row);
 261	scr_memsetw(d + (b - t - nr) * vc->vc_cols, vc->vc_video_erase_char,
 262		    vc->vc_size_row * nr);
 263}
 264
 265static void scrdown(struct vc_data *vc, unsigned int t, unsigned int b, int nr)
 266{
 267	unsigned short *s;
 268	unsigned int step;
 269
 270	if (t+nr >= b)
 271		nr = b - t - 1;
 272	if (b > vc->vc_rows || t >= b || nr < 1)
 273		return;
 274	if (CON_IS_VISIBLE(vc) && vc->vc_sw->con_scroll(vc, t, b, SM_DOWN, nr))
 275		return;
 276	s = (unsigned short *)(vc->vc_origin + vc->vc_size_row * t);
 277	step = vc->vc_cols * nr;
 278	scr_memmovew(s + step, s, (b - t - nr) * vc->vc_size_row);
 279	scr_memsetw(s, vc->vc_video_erase_char, 2 * step);
 280}
 281
 282static void do_update_region(struct vc_data *vc, unsigned long start, int count)
 283{
 284#ifndef VT_BUF_VRAM_ONLY
 285	unsigned int xx, yy, offset;
 286	u16 *p;
 287
 288	p = (u16 *) start;
 289	if (!vc->vc_sw->con_getxy) {
 290		offset = (start - vc->vc_origin) / 2;
 291		xx = offset % vc->vc_cols;
 292		yy = offset / vc->vc_cols;
 293	} else {
 294		int nxx, nyy;
 295		start = vc->vc_sw->con_getxy(vc, start, &nxx, &nyy);
 296		xx = nxx; yy = nyy;
 297	}
 298	for(;;) {
 299		u16 attrib = scr_readw(p) & 0xff00;
 300		int startx = xx;
 301		u16 *q = p;
 302		while (xx < vc->vc_cols && count) {
 303			if (attrib != (scr_readw(p) & 0xff00)) {
 304				if (p > q)
 305					vc->vc_sw->con_putcs(vc, q, p-q, yy, startx);
 306				startx = xx;
 307				q = p;
 308				attrib = scr_readw(p) & 0xff00;
 309			}
 310			p++;
 311			xx++;
 312			count--;
 313		}
 314		if (p > q)
 315			vc->vc_sw->con_putcs(vc, q, p-q, yy, startx);
 316		if (!count)
 317			break;
 318		xx = 0;
 319		yy++;
 320		if (vc->vc_sw->con_getxy) {
 321			p = (u16 *)start;
 322			start = vc->vc_sw->con_getxy(vc, start, NULL, NULL);
 323		}
 324	}
 325#endif
 326}
 327
 328void update_region(struct vc_data *vc, unsigned long start, int count)
 329{
 330	WARN_CONSOLE_UNLOCKED();
 331
 332	if (DO_UPDATE(vc)) {
 333		hide_cursor(vc);
 334		do_update_region(vc, start, count);
 335		set_cursor(vc);
 336	}
 337}
 338
 339/* Structure of attributes is hardware-dependent */
 340
 341static u8 build_attr(struct vc_data *vc, u8 _color, u8 _intensity, u8 _blink, u8 _underline, u8 _reverse)
 342{
 343	if (vc->vc_sw->con_build_attr)
 344		return vc->vc_sw->con_build_attr(vc, _color, _intensity, _blink, _underline, _reverse);
 345
 346#ifndef VT_BUF_VRAM_ONLY
 347/*
 348 * ++roman: I completely changed the attribute format for monochrome
 349 * mode (!can_do_color). The formerly used MDA (monochrome display
 350 * adapter) format didn't allow the combination of certain effects.
 351 * Now the attribute is just a bit vector:
 352 *  Bit 0..1: intensity (0..2)
 353 *  Bit 2   : underline
 354 *  Bit 3   : reverse
 355 *  Bit 7   : blink
 356 */
 357	{
 358	u8 a = vc->vc_color;
 359	if (!vc->vc_can_do_color)
 360		return _intensity |
 361		       (_underline ? 4 : 0) |
 362		       (_reverse ? 8 : 0) |
 363		       (_blink ? 0x80 : 0);
 364	if (_underline)
 365		a = (a & 0xf0) | vc->vc_ulcolor;
 366	else if (_intensity == 0)
 367		a = (a & 0xf0) | vc->vc_ulcolor;
 368	if (_reverse)
 369		a = ((a) & 0x88) | ((((a) >> 4) | ((a) << 4)) & 0x77);
 370	if (_blink)
 371		a ^= 0x80;
 372	if (_intensity == 2)
 373		a ^= 0x08;
 374	if (vc->vc_hi_font_mask == 0x100)
 375		a <<= 1;
 376	return a;
 377	}
 378#else
 379	return 0;
 380#endif
 381}
 382
 383static void update_attr(struct vc_data *vc)
 384{
 385	vc->vc_attr = build_attr(vc, vc->vc_color, vc->vc_intensity, vc->vc_blink, vc->vc_underline, vc->vc_reverse ^ vc->vc_decscnm);
 386	vc->vc_video_erase_char = (build_attr(vc, vc->vc_color, 1, vc->vc_blink, 0, vc->vc_decscnm) << 8) | ' ';
 387}
 388
 389/* Note: inverting the screen twice should revert to the original state */
 390void invert_screen(struct vc_data *vc, int offset, int count, int viewed)
 391{
 392	unsigned short *p;
 393
 394	WARN_CONSOLE_UNLOCKED();
 395
 396	count /= 2;
 397	p = screenpos(vc, offset, viewed);
 398	if (vc->vc_sw->con_invert_region)
 399		vc->vc_sw->con_invert_region(vc, p, count);
 400#ifndef VT_BUF_VRAM_ONLY
 401	else {
 402		u16 *q = p;
 403		int cnt = count;
 404		u16 a;
 405
 406		if (!vc->vc_can_do_color) {
 407			while (cnt--) {
 408			    a = scr_readw(q);
 409			    a ^= 0x0800;
 410			    scr_writew(a, q);
 411			    q++;
 412			}
 413		} else if (vc->vc_hi_font_mask == 0x100) {
 414			while (cnt--) {
 415				a = scr_readw(q);
 416				a = ((a) & 0x11ff) | (((a) & 0xe000) >> 4) | (((a) & 0x0e00) << 4);
 417				scr_writew(a, q);
 418				q++;
 419			}
 420		} else {
 421			while (cnt--) {
 422				a = scr_readw(q);
 423				a = ((a) & 0x88ff) | (((a) & 0x7000) >> 4) | (((a) & 0x0700) << 4);
 424				scr_writew(a, q);
 425				q++;
 426			}
 427		}
 428	}
 429#endif
 430	if (DO_UPDATE(vc))
 431		do_update_region(vc, (unsigned long) p, count);
 432}
 433
 434/* used by selection: complement pointer position */
 435void complement_pos(struct vc_data *vc, int offset)
 436{
 437	static unsigned short *p;
 438	static unsigned short old;
 439	static unsigned short oldx, oldy;
 440
 441	WARN_CONSOLE_UNLOCKED();
 442
 443	if (p) {
 444		scr_writew(old, p);
 445		if (DO_UPDATE(vc))
 446			vc->vc_sw->con_putc(vc, old, oldy, oldx);
 447	}
 448	if (offset == -1)
 449		p = NULL;
 450	else {
 451		unsigned short new;
 452		p = screenpos(vc, offset, 1);
 453		old = scr_readw(p);
 454		new = old ^ vc->vc_complement_mask;
 455		scr_writew(new, p);
 456		if (DO_UPDATE(vc)) {
 457			oldx = (offset >> 1) % vc->vc_cols;
 458			oldy = (offset >> 1) / vc->vc_cols;
 459			vc->vc_sw->con_putc(vc, new, oldy, oldx);
 460		}
 461	}
 462}
 463
 464static void insert_char(struct vc_data *vc, unsigned int nr)
 465{
 466	unsigned short *p, *q = (unsigned short *)vc->vc_pos;
 467
 468	p = q + vc->vc_cols - nr - vc->vc_x;
 469	while (--p >= q)
 470		scr_writew(scr_readw(p), p + nr);
 471	scr_memsetw(q, vc->vc_video_erase_char, nr * 2);
 472	vc->vc_need_wrap = 0;
 473	if (DO_UPDATE(vc)) {
 474		unsigned short oldattr = vc->vc_attr;
 475		vc->vc_sw->con_bmove(vc, vc->vc_y, vc->vc_x, vc->vc_y, vc->vc_x + nr, 1,
 476				     vc->vc_cols - vc->vc_x - nr);
 477		vc->vc_attr = vc->vc_video_erase_char >> 8;
 478		while (nr--)
 479			vc->vc_sw->con_putc(vc, vc->vc_video_erase_char, vc->vc_y, vc->vc_x + nr);
 480		vc->vc_attr = oldattr;
 481	}
 482}
 483
 484static void delete_char(struct vc_data *vc, unsigned int nr)
 485{
 486	unsigned int i = vc->vc_x;
 487	unsigned short *p = (unsigned short *)vc->vc_pos;
 488
 489	while (++i <= vc->vc_cols - nr) {
 490		scr_writew(scr_readw(p+nr), p);
 491		p++;
 492	}
 493	scr_memsetw(p, vc->vc_video_erase_char, nr * 2);
 494	vc->vc_need_wrap = 0;
 495	if (DO_UPDATE(vc)) {
 496		unsigned short oldattr = vc->vc_attr;
 497		vc->vc_sw->con_bmove(vc, vc->vc_y, vc->vc_x + nr, vc->vc_y, vc->vc_x, 1,
 498				     vc->vc_cols - vc->vc_x - nr);
 499		vc->vc_attr = vc->vc_video_erase_char >> 8;
 500		while (nr--)
 501			vc->vc_sw->con_putc(vc, vc->vc_video_erase_char, vc->vc_y,
 502				     vc->vc_cols - 1 - nr);
 503		vc->vc_attr = oldattr;
 504	}
 505}
 506
 507static int softcursor_original;
 508
 509static void add_softcursor(struct vc_data *vc)
 510{
 511	int i = scr_readw((u16 *) vc->vc_pos);
 512	u32 type = vc->vc_cursor_type;
 513
 514	if (! (type & 0x10)) return;
 515	if (softcursor_original != -1) return;
 516	softcursor_original = i;
 517	i |= ((type >> 8) & 0xff00 );
 518	i ^= ((type) & 0xff00 );
 519	if ((type & 0x20) && ((softcursor_original & 0x7000) == (i & 0x7000))) i ^= 0x7000;
 520	if ((type & 0x40) && ((i & 0x700) == ((i & 0x7000) >> 4))) i ^= 0x0700;
 521	scr_writew(i, (u16 *) vc->vc_pos);
 522	if (DO_UPDATE(vc))
 523		vc->vc_sw->con_putc(vc, i, vc->vc_y, vc->vc_x);
 524}
 525
 526static void hide_softcursor(struct vc_data *vc)
 527{
 528	if (softcursor_original != -1) {
 529		scr_writew(softcursor_original, (u16 *)vc->vc_pos);
 530		if (DO_UPDATE(vc))
 531			vc->vc_sw->con_putc(vc, softcursor_original,
 532					vc->vc_y, vc->vc_x);
 533		softcursor_original = -1;
 534	}
 535}
 536
 537static void hide_cursor(struct vc_data *vc)
 538{
 539	if (vc == sel_cons)
 540		clear_selection();
 541	vc->vc_sw->con_cursor(vc, CM_ERASE);
 542	hide_softcursor(vc);
 543}
 544
 545static void set_cursor(struct vc_data *vc)
 546{
 547	if (!IS_FG(vc) || console_blanked ||
 548	    vc->vc_mode == KD_GRAPHICS)
 549		return;
 550	if (vc->vc_deccm) {
 551		if (vc == sel_cons)
 552			clear_selection();
 553		add_softcursor(vc);
 554		if ((vc->vc_cursor_type & 0x0f) != 1)
 555			vc->vc_sw->con_cursor(vc, CM_DRAW);
 556	} else
 557		hide_cursor(vc);
 558}
 559
 560static void set_origin(struct vc_data *vc)
 561{
 562	WARN_CONSOLE_UNLOCKED();
 563
 564	if (!CON_IS_VISIBLE(vc) ||
 565	    !vc->vc_sw->con_set_origin ||
 566	    !vc->vc_sw->con_set_origin(vc))
 567		vc->vc_origin = (unsigned long)vc->vc_screenbuf;
 568	vc->vc_visible_origin = vc->vc_origin;
 569	vc->vc_scr_end = vc->vc_origin + vc->vc_screenbuf_size;
 570	vc->vc_pos = vc->vc_origin + vc->vc_size_row * vc->vc_y + 2 * vc->vc_x;
 571}
 572
 573static inline void save_screen(struct vc_data *vc)
 574{
 575	WARN_CONSOLE_UNLOCKED();
 576
 577	if (vc->vc_sw->con_save_screen)
 578		vc->vc_sw->con_save_screen(vc);
 579}
 580
 581/*
 582 *	Redrawing of screen
 583 */
 584
 585static void clear_buffer_attributes(struct vc_data *vc)
 586{
 587	unsigned short *p = (unsigned short *)vc->vc_origin;
 588	int count = vc->vc_screenbuf_size / 2;
 589	int mask = vc->vc_hi_font_mask | 0xff;
 590
 591	for (; count > 0; count--, p++) {
 592		scr_writew((scr_readw(p)&mask) | (vc->vc_video_erase_char & ~mask), p);
 593	}
 594}
 595
 596void redraw_screen(struct vc_data *vc, int is_switch)
 597{
 598	int redraw = 0;
 599
 600	WARN_CONSOLE_UNLOCKED();
 601
 602	if (!vc) {
 603		/* strange ... */
 604		/* printk("redraw_screen: tty %d not allocated ??\n", new_console+1); */
 605		return;
 606	}
 607
 608	if (is_switch) {
 609		struct vc_data *old_vc = vc_cons[fg_console].d;
 610		if (old_vc == vc)
 611			return;
 612		if (!CON_IS_VISIBLE(vc))
 613			redraw = 1;
 614		*vc->vc_display_fg = vc;
 615		fg_console = vc->vc_num;
 616		hide_cursor(old_vc);
 617		if (!CON_IS_VISIBLE(old_vc)) {
 618			save_screen(old_vc);
 619			set_origin(old_vc);
 620		}
 621	} else {
 622		hide_cursor(vc);
 623		redraw = 1;
 624	}
 625
 626	if (redraw) {
 627		int update;
 628		int old_was_color = vc->vc_can_do_color;
 629
 630		set_origin(vc);
 631		update = vc->vc_sw->con_switch(vc);
 632		set_palette(vc);
 633		/*
 634		 * If console changed from mono<->color, the best we can do
 635		 * is to clear the buffer attributes. As it currently stands,
 636		 * rebuilding new attributes from the old buffer is not doable
 637		 * without overly complex code.
 638		 */
 639		if (old_was_color != vc->vc_can_do_color) {
 640			update_attr(vc);
 641			clear_buffer_attributes(vc);
 642		}
 643		if (update && vc->vc_mode != KD_GRAPHICS)
 644			do_update_region(vc, vc->vc_origin, vc->vc_screenbuf_size / 2);
 645	}
 646	set_cursor(vc);
 647	if (is_switch) {
 648		set_leds();
 649		compute_shiftstate();
 650	}
 651}
 652
 653/*
 654 *	Allocation, freeing and resizing of VTs.
 655 */
 656
 657int vc_cons_allocated(unsigned int i)
 658{
 659	return (i < MAX_NR_CONSOLES && vc_cons[i].d);
 660}
 661
 662static void visual_init(struct vc_data *vc, int num, int init)
 663{
 664	/* ++Geert: vc->vc_sw->con_init determines console size */
 665	if (vc->vc_sw)
 666		module_put(vc->vc_sw->owner);
 667	vc->vc_sw = conswitchp;
 668#ifndef VT_SINGLE_DRIVER
 669	if (con_driver_map[num])
 670		vc->vc_sw = con_driver_map[num];
 671#endif
 672	__module_get(vc->vc_sw->owner);
 673	vc->vc_num = num;
 674	vc->vc_display_fg = &master_display_fg;
 675	vc->vc_uni_pagedir_loc = &vc->vc_uni_pagedir;
 676	vc->vc_uni_pagedir = 0;
 677	vc->vc_hi_font_mask = 0;
 678	vc->vc_complement_mask = 0;
 679	vc->vc_can_do_color = 0;
 680	vc->vc_sw->con_init(vc, init);
 681	if (!vc->vc_complement_mask)
 682		vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
 683	vc->vc_s_complement_mask = vc->vc_complement_mask;
 684	vc->vc_size_row = vc->vc_cols << 1;
 685	vc->vc_screenbuf_size = vc->vc_rows * vc->vc_size_row;
 686}
 687
 688int vc_allocate(unsigned int currcons)	/* return 0 on success */
 689{
 690	WARN_CONSOLE_UNLOCKED();
 691
 692	if (currcons >= MAX_NR_CONSOLES)
 693		return -ENXIO;
 694	if (!vc_cons[currcons].d) {
 695	    struct vc_data *vc;
 696
 697	    /* prevent users from taking too much memory */
 698	    if (currcons >= MAX_NR_USER_CONSOLES && !capable(CAP_SYS_RESOURCE))
 699	      return -EPERM;
 700
 701	    /* due to the granularity of kmalloc, we waste some memory here */
 702	    /* the alloc is done in two steps, to optimize the common situation
 703	       of a 25x80 console (structsize=216, screenbuf_size=4000) */
 704	    /* although the numbers above are not valid since long ago, the
 705	       point is still up-to-date and the comment still has its value
 706	       even if only as a historical artifact.  --mj, July 1998 */
 707	    vc = kmalloc(sizeof(struct vc_data), GFP_KERNEL);
 708	    if (!vc)
 709		return -ENOMEM;
 710	    memset(vc, 0, sizeof(*vc));
 711	    vc_cons[currcons].d = vc;
 712	    visual_init(vc, currcons, 1);
 713	    if (!*vc->vc_uni_pagedir_loc)
 714		con_set_default_unimap(vc);
 715	    vc->vc_screenbuf = kmalloc(vc->vc_screenbuf_size, GFP_KERNEL);
 716	    if (!vc->vc_screenbuf) {
 717		kfree(vc);
 718		vc_cons[currcons].d = NULL;
 719		return -ENOMEM;
 720	    }
 721	    vc->vc_kmalloced = 1;
 722	    vc_init(vc, vc->vc_rows, vc->vc_cols, 1);
 723	}
 724	return 0;
 725}
 726
 727static inline int resize_screen(struct vc_data *vc, int width, int height)
 728{
 729	/* Resizes the resolution of the display adapater */
 730	int err = 0;
 731
 732	if (vc->vc_mode != KD_GRAPHICS && vc->vc_sw->con_resize)
 733		err = vc->vc_sw->con_resize(vc, width, height);
 734	return err;
 735}
 736
 737/*
 738 * Change # of rows and columns (0 means unchanged/the size of fg_console)
 739 * [this is to be used together with some user program
 740 * like resize that changes the hardware videomode]
 741 */
 742#define VC_RESIZE_MAXCOL (32767)
 743#define VC_RESIZE_MAXROW (32767)
 744int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines)
 745{
 746	unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0;
 747	unsigned int old_cols, old_rows, old_row_size, old_screen_size;
 748	unsigned int new_cols, new_rows, new_row_size, new_screen_size;
 749	unsigned short *newscreen;
 750
 751	WARN_CONSOLE_UNLOCKED();
 752
 753	if (!vc)
 754		return -ENXIO;
 755
 756	if (cols > VC_RESIZE_MAXCOL || lines > VC_RESIZE_MAXROW)
 757		return -EINVAL;
 758
 759	new_cols = (cols ? cols : vc->vc_cols);
 760	new_rows = (lines ? lines : vc->vc_rows);
 761	new_row_size = new_cols << 1;
 762	new_screen_size = new_row_size * new_rows;
 763
 764	if (new_cols == vc->vc_cols && new_rows == vc->vc_rows)
 765		return 0;
 766
 767	newscreen = (unsigned short *) kmalloc(new_screen_size, GFP_USER);
 768	if (!newscreen)
 769		return -ENOMEM;
 770
 771	old_rows = vc->vc_rows;
 772	old_cols = vc->vc_cols;
 773	old_row_size = vc->vc_size_row;
 774	old_screen_size = vc->vc_screenbuf_size;
 775
 776	err = resize_screen(vc, new_cols, new_rows);
 777	if (err) {
 778		kfree(newscreen);
 779		return err;
 780	}
 781
 782	vc->vc_rows = new_rows;
 783	vc->vc_cols = new_cols;
 784	vc->vc_size_row = new_row_size;
 785	vc->vc_screenbuf_size = new_screen_size;
 786
 787	rlth = min(old_row_size, new_row_size);
 788	rrem = new_row_size - rlth;
 789	old_origin = vc->vc_origin;
 790	new_origin = (long) newscreen;
 791	new_scr_end = new_origin + new_screen_size;
 792	if (new_rows < old_rows)
 793		old_origin += (old_rows - new_rows) * old_row_size;
 794
 795	update_attr(vc);
 796
 797	while (old_origin < vc->vc_scr_end) {
 798		scr_memcpyw((unsigned short *) new_origin, (unsigned short *) old_origin, rlth);
 799		if (rrem)
 800			scr_memsetw((void *)(new_origin + rlth), vc->vc_video_erase_char, rrem);
 801		old_origin += old_row_size;
 802		new_origin += new_row_size;
 803	}
 804	if (new_scr_end > new_origin)
 805		scr_memsetw((void *)new_origin, vc->vc_video_erase_char, new_scr_end - new_origin);
 806	if (vc->vc_kmalloced)
 807		kfree(vc->vc_screenbuf);
 808	vc->vc_screenbuf = newscreen;
 809	vc->vc_kmalloced = 1;
 810	vc->vc_screenbuf_size = new_screen_size;
 811	set_origin(vc);
 812
 813	/* do part of a reset_terminal() */
 814	vc->vc_top = 0;
 815	vc->vc_bottom = vc->vc_rows;
 816	gotoxy(vc, vc->vc_x, vc->vc_y);
 817	save_cur(vc);
 818
 819	if (vc->vc_tty) {
 820		struct winsize ws, *cws = &vc->vc_tty->winsize;
 821
 822		memset(&ws, 0, sizeof(ws));
 823		ws.ws_row = vc->vc_rows;
 824		ws.ws_col = vc->vc_cols;
 825		ws.ws_ypixel = vc->vc_scan_lines;
 826		if ((ws.ws_row != cws->ws_row || ws.ws_col != cws->ws_col) &&
 827		    vc->vc_tty->pgrp > 0)
 828			kill_pg(vc->vc_tty->pgrp, SIGWINCH, 1);
 829		*cws = ws;
 830	}
 831
 832	if (CON_IS_VISIBLE(vc))
 833		update_screen(vc);
 834	return err;
 835}
 836
 837
 838void vc_disallocate(unsigned int currcons)
 839{
 840	WARN_CONSOLE_UNLOCKED();
 841
 842	if (vc_cons_allocated(currcons)) {
 843		struct vc_data *vc = vc_cons[currcons].d;
 844		vc->vc_sw->con_deinit(vc);
 845		if (vc->vc_kmalloced)
 846			kfree(vc->vc_screenbuf);
 847		if (currcons >= MIN_NR_CONSOLES)
 848			kfree(vc);
 849		vc_cons[currcons].d = NULL;
 850	}
 851}
 852
 853/*
 854 *	VT102 emulator
 855 */
 856
 857#define set_kbd(vc, x)	set_vc_kbd_mode(kbd_table + (vc)->vc_num, (x))
 858#define clr_kbd(vc, x)	clr_vc_kbd_mode(kbd_table + (vc)->vc_num, (x))
 859#define is_kbd(vc, x)	vc_kbd_mode(kbd_table + (vc)->vc_num, (x))
 860
 861#define decarm		VC_REPEAT
 862#define decckm		VC_CKMODE
 863#define kbdapplic	VC_APPLIC
 864#define lnm		VC_CRLF
 865
 866/*
 867 * this is what the terminal answers to a ESC-Z or csi0c query.
 868 */
 869#define VT100ID "\033[?1;2c"
 870#define VT102ID "\033[?6c"
 871
 872unsigned char color_table[] = { 0, 4, 2, 6, 1, 5, 3, 7,
 873				       8,12,10,14, 9,13,11,15 };
 874
 875/* the default colour table, for VGA+ colour systems */
 876int default_red[] = {0x00,0xaa,0x00,0xaa,0x00,0xaa,0x00,0xaa,
 877    0x55,0xff,0x55,0xff,0x55,0xff,0x55,0xff};
 878int default_grn[] = {0x00,0x00,0xaa,0x55,0x00,0x00,0xaa,0xaa,
 879    0x55,0x55,0xff,0xff,0x55,0x55,0xff,0xff};
 880int default_blu[] = {0x00,0x00,0x00,0x00,0xaa,0xaa,0xaa,0xaa,
 881    0x55,0x55,0x55,0x55,0xff,0xff,0xff,0xff};
 882
 883/*
 884 * gotoxy() must verify all boundaries, because the arguments
 885 * might also be negative. If the given position is out of
 886 * bounds, the cursor is placed at the nearest margin.
 887 */
 888static void gotoxy(struct vc_data *vc, int new_x, int new_y)
 889{
 890	int min_y, max_y;
 891
 892	if (new_x < 0)
 893		vc->vc_x = 0;
 894	else {
 895		if (new_x >= vc->vc_cols)
 896			vc->vc_x = vc->vc_cols - 1;
 897		else
 898			vc->vc_x = new_x;
 899	}
 900
 901 	if (vc->vc_decom) {
 902		min_y = vc->vc_top;
 903		max_y = vc->vc_bottom;
 904	} else {
 905		min_y = 0;
 906		max_y = vc->vc_rows;
 907	}
 908	if (new_y < min_y)
 909		vc->vc_y = min_y;
 910	else if (new_y >= max_y)
 911		vc->vc_y = max_y - 1;
 912	else
 913		vc->vc_y = new_y;
 914	vc->vc_pos = vc->vc_origin + vc->vc_y * vc->vc_size_row + (vc->vc_x<<1);
 915	vc->vc_need_wrap = 0;
 916}
 917
 918/* for absolute user moves, when decom is set */
 919static void gotoxay(struct vc_data *vc, int new_x, int new_y)
 920{
 921	gotoxy(vc, new_x, vc->vc_decom ? (vc->vc_top + new_y) : new_y);
 922}
 923
 924void scrollback(struct vc_data *vc, int lines)
 925{
 926	if (!lines)
 927		lines = vc->vc_rows / 2;
 928	scrolldelta(-lines);
 929}
 930
 931void scrollfront(struct vc_data *vc, int lines)
 932{
 933	if (!lines)
 934		lines = vc->vc_rows / 2;
 935	scrolldelta(lines);
 936}
 937
 938static void lf(struct vc_data *vc)
 939{
 940    	/* don't scroll if above bottom of scrolling region, or
 941	 * if below scrolling region
 942	 */
 943    	if (vc->vc_y + 1 == vc->vc_bottom)
 944		scrup(vc, vc->vc_top, vc->vc_bottom, 1);
 945	else if (vc->vc_y < vc->vc_rows - 1) {
 946	    	vc->vc_y++;
 947		vc->vc_pos += vc->vc_size_row;
 948	}
 949	vc->vc_need_wrap = 0;
 950}
 951
 952static void ri(struct vc_data *vc)
 953{
 954    	/* don't scroll if below top of scrolling region, or
 955	 * if above scrolling region
 956	 */
 957	if (vc->vc_y == vc->vc_top)
 958		scrdown(vc, vc->vc_top, vc->vc_bottom, 1);
 959	else if (vc->vc_y > 0) {
 960		vc->vc_y--;
 961		vc->vc_pos -= vc->vc_size_row;
 962	}
 963	vc->vc_need_wrap = 0;
 964}
 965
 966static inline void cr(struct vc_data *vc)
 967{
 968	vc->vc_pos -= vc->vc_x << 1;
 969	vc->vc_need_wrap = vc->vc_x = 0;
 970}
 971
 972static inline void bs(struct vc_data *vc)
 973{
 974	if (vc->vc_x) {
 975		vc->vc_pos -= 2;
 976		vc->vc_x--;
 977		vc->vc_need_wrap = 0;
 978	}
 979}
 980
 981static inline void del(struct vc_data *vc)
 982{
 983	/* ignored */
 984}
 985
 986static void csi_J(struct vc_data *vc, int vpar)
 987{
 988	unsigned int count;
 989	unsigned short * start;
 990
 991	switch (vpar) {
 992		case 0:	/* erase from cursor to end of display */
 993			count = (vc->vc_scr_end - vc->vc_pos) >> 1;
 994			start = (unsigned short *)vc->vc_pos;
 995			if (DO_UPDATE(vc)) {
 996				/* do in two stages */
 997				vc->vc_sw->con_clear(vc, vc->vc_y, vc->vc_x, 1,
 998					      vc->vc_cols - vc->vc_x);
 999				vc->vc_sw->con_clear(vc, vc->vc_y + 1, 0,
1000					      vc->vc_rows - vc->vc_y - 1,
1001					      vc->vc_cols);
1002			}
1003			break;
1004		case 1:	/* erase from start to cursor */
1005			count = ((vc->vc_pos - vc->vc_origin) >> 1) + 1;
1006			start = (unsigned short *)vc->vc_origin;
1007			if (DO_UPDATE(vc)) {
1008				/* do in two stages */
1009				vc->vc_sw->con_clear(vc, 0, 0, vc->vc_y,
1010					      vc->vc_cols);
1011				vc->vc_sw->con_clear(vc, vc->vc_y, 0, 1,
1012					      vc->vc_x + 1);
1013			}
1014			break;
1015		case 2: /* erase whole display */
1016			count = vc->vc_cols * vc->vc_rows;
1017			start = (unsigned short *)vc->vc_origin;
1018			if (DO_UPDATE(vc))
1019				vc->vc_sw->con_clear(vc, 0, 0,
1020					      vc->vc_rows,
1021					      vc->vc_cols);
1022			break;
1023		default:
1024			return;
1025	}
1026	scr_memsetw(start, vc->vc_video_erase_char, 2 * count);
1027	vc->vc_need_wrap = 0;
1028}
1029
1030static void csi_K(struct vc_data *vc, int vpar)
1031{
1032	unsigned int count;
1033	unsigned short * start;
1034
1035	switch (vpar) {
1036		case 0:	/* erase from cursor to end of line */
1037			count = vc->vc_cols - vc->vc_x;
1038			start = (unsigned short *)vc->vc_pos;
1039			if (DO_UPDATE(vc))
1040				vc->vc_sw->con_clear(vc, vc->vc_y, vc->vc_x, 1,
1041						     vc->vc_cols - vc->vc_x);
1042			break;
1043		case 1:	/* erase from start of line to cursor */
1044			start = (unsigned short *)(vc->vc_pos - (vc->vc_x << 1));
1045			count = vc->vc_x + 1;
1046			if (DO_UPDATE(vc))
1047				vc->vc_sw->con_clear(vc, vc->vc_y, 0, 1,
1048						     vc->vc_x + 1);
1049			break;
1050		case 2: /* erase whole line */
1051			start = (unsigned short *)(vc->vc_pos - (vc->vc_x << 1));
1052			count = vc->vc_cols;
1053			if (DO_UPDATE(vc))
1054				vc->vc_sw->con_clear(vc, vc->vc_y, 0, 1,
1055					      vc->vc_cols);
1056			break;
1057		default:
1058			return;
1059	}
1060	scr_memsetw(start, vc->vc_video_erase_char, 2 * count);
1061	vc->vc_need_wrap = 0;
1062}
1063
1064static void csi_X(struct vc_data *vc, int vpar) /* erase the following vpar positions */
1065{					  /* not vt100? */
1066	int count;
1067
1068	if (!vpar)
1069		vpar++;
1070	count = (vpar > vc->vc_cols - vc->vc_x) ? (vc->vc_cols - vc->vc_x) : vpar;
1071
1072	scr_memsetw((unsigned short *)vc->vc_pos, vc->vc_video_erase_char, 2 * count);
1073	if (DO_UPDATE(vc))
1074		vc->vc_sw->con_clear(vc, vc->vc_y, vc->vc_x, 1, count);
1075	vc->vc_need_wrap = 0;
1076}
1077
1078static void default_attr(struct vc_data *vc)
1079{
1080	vc->vc_intensity = 1;
1081	vc->vc_underline = 0;
1082	vc->vc_reverse = 0;
1083	vc->vc_blink = 0;
1084	vc->vc_color = vc->vc_def_color;
1085}
1086
1087/* console_sem is held */
1088static void csi_m(struct vc_data *vc)
1089{
1090	int i;
1091
1092	for (i = 0; i <= vc->vc_npar; i++)
1093		switch (vc->vc_par[i]) {
1094			case 0:	/* all attributes off */
1095				default_attr(vc);
1096				break;
1097			case 1:
1098				vc->vc_intensity = 2;
1099				break;
1100			case 2:
1101				vc->vc_intensity = 0;
1102				break;
1103			case 4:
1104				vc->vc_underline = 1;
1105				break;
1106			case 5:
1107				vc->vc_blink = 1;
1108				break;
1109			case 7:
1110				vc->vc_reverse = 1;
1111				break;
1112			case 10: /* ANSI X3.64-1979 (SCO-ish?)
1113				  * Select primary font, don't display
1114				  * control chars if defined, don't set
1115				  * bit 8 on output.
1116				  */
1117				vc->vc_translate = set_translate(vc->vc_charset == 0
1118						? vc->vc_G0_charset
1119						: vc->vc_G1_charset, vc);
1120				vc->vc_disp_ctrl = 0;
1121				vc->vc_toggle_meta = 0;
1122				break;
1123			case 11: /* ANSI X3.64-1979 (SCO-ish?)
1124				  * Select first alternate font, lets
1125				  * chars < 32 be displayed as ROM chars.
1126				  */
1127				vc->vc_translate = set_translate(IBMPC_MAP, vc);
1128				vc->vc_disp_ctrl = 1;
1129				vc->vc_toggle_meta = 0;
1130				break;
1131			case 12: /* ANSI X3.64-1979 (SCO-ish?)
1132				  * Select second alternate font, toggle
1133				  * high bit before displaying as ROM char.
1134				  */
1135				vc->vc_translate = set_translate(IBMPC_MAP, vc);
1136				vc->vc_disp_ctrl = 1;
1137				vc->vc_toggle_meta = 1;
1138				break;
1139			case 21:
1140			case 22:
1141				vc->vc_intensity = 1;
1142				break;
1143			case 24:
1144				vc->vc_underline = 0;
1145				break;
1146			case 25:
1147				vc->vc_blink = 0;
1148				break;
1149			case 27:
1150				vc->vc_reverse = 0;
1151				break;
1152			case 38: /* ANSI X3.64-1979 (SCO-ish?)
1153				  * Enables underscore, white foreground
1154				  * with white underscore (Linux - use
1155				  * default foreground).
1156				  */
1157				vc->vc_color = (vc->vc_def_color & 0x0f) | (vc->vc_color & 0xf0);
1158				vc->vc_underline = 1;
1159				break;
1160			case 39: /* ANSI X3.64-1979 (SCO-ish?)
1161				  * Disable underline option.
1162				  * Reset colour to default? It did this
1163				  * before...
1164				  */
1165				vc->vc_color = (vc->vc_def_color & 0x0f) | (vc->vc_color & 0xf0);
1166				vc->vc_underline = 0;
1167				break;
1168			case 49:
1169				vc->vc_color = (vc->vc_def_color & 0xf0) | (vc->vc_color & 0x0f);
1170				break;
1171			default:
1172				if (vc->vc_par[i] >= 30 && vc->vc_par[i] <= 37)
1173					vc->vc_color = color_table[vc->vc_par[i] - 30]
1174						| (vc->vc_color & 0xf0);
1175				else if (vc->vc_par[i] >= 40 && vc->vc_par[i] <= 47)
1176					vc->vc_color = (color_table[vc->vc_par[i] - 40] << 4)
1177						| (vc->vc_color & 0x0f);
1178				break;
1179		}
1180	update_attr(vc);
1181}
1182
1183static void respond_string(const char *p, struct tty_struct *tty)
1184{
1185	while (*p) {
1186		tty_insert_flip_char(tty, *p, 0);
1187		p++;
1188	}
1189	con_schedule_flip(tty);
1190}
1191
1192static void cursor_report(struct vc_data *vc, struct tty_struct *tty)
1193{
1194	char buf[40];
1195
1196	sprintf(buf, "\033[%d;%dR", vc->vc_y + (vc->vc_decom ? vc->vc_top + 1 : 1), vc->vc_x + 1);
1197	respond_string(buf, tty);
1198}
1199
1200static inline void status_report(struct tty_struct *tty)
1201{
1202	respond_string("\033[0n", tty);	/* Terminal ok */
1203}
1204
1205static inline void respond_ID(struct tty_struct * tty)
1206{
1207	respond_string(VT102ID, tty);
1208}
1209
1210void mouse_report(struct tty_struct *tty, int butt, int mrx, int mry)
1211{
1212	char buf[8];
1213
1214	sprintf(buf, "\033[M%c%c%c", (char)(' ' + butt), (char)('!' + mrx),
1215		(char)('!' + mry));
1216	respond_string(buf, tty);
1217}
1218
1219/* invoked via ioctl(TIOCLINUX) and through set_selection */
1220int mouse_reporting(void)
1221{
1222	return vc_cons[fg_console].d->vc_report_mouse;
1223}
1224
1225/* console_sem is held */
1226static void set_mode(struct vc_data *vc, int on_off)
1227{
1228	int i;
1229
1230	for (i = 0; i <= vc->vc_npar; i++)
1231		if (vc->vc_ques) {
1232			switch(vc->vc_par[i]) {	/* DEC private modes set/reset */
1233			case 1:			/* Cursor keys send ^[Ox/^[[x */
1234				if (on_off)
1235					set_kbd(vc, decckm);
1236				else
1237					clr_kbd(vc, decckm);
1238				break;
1239			case 3:	/* 80/132 mode switch unimplemented */
1240				vc->vc_deccolm = on_off;
1241#if 0
1242				vc_resize(deccolm ? 132 : 80, vc->vc_rows);
1243				/* this alone does not suffice; some user mode
1244				   utility has to change the hardware regs */
1245#endif
1246				break;
1247			case 5:			/* Inverted screen on/off */
1248				if (vc->vc_decscnm != on_off) {
1249					vc->vc_decscnm = on_off;
1250					invert_screen(vc, 0, vc->vc_screenbuf_size, 0);
1251					update_attr(vc);
1252				}
1253				break;
1254			case 6:			/* Origin relative/absolute */
1255				vc->vc_decom = on_off;
1256				gotoxay(vc, 0, 0);
1257				break;
1258			case 7:			/* Autowrap on/off */
1259				vc->vc_decawm = on_off;
1260				break;
1261			case 8:			/* Autorepeat on/off */
1262				if (on_off)
1263					set_kbd(vc, decarm);
1264				else
1265					clr_kbd(vc, decarm);
1266				break;
1267			case 9:
1268				vc->vc_report_mouse = on_off ? 1 : 0;
1269				break;
1270			case 25:		/* Cursor on/off */
1271				vc->vc_deccm = on_off;
1272				break;
1273			case 1000:
1274				vc->vc_report_mouse = on_off ? 2 : 0;
1275				break;
1276			}
1277		} else {
1278			switch(vc->vc_par[i]) {	/* ANSI modes set/reset */
1279			case 3:			/* Monitor (display ctrls) */
1280				vc->vc_disp_ctrl = on_off;
1281				break;
1282			case 4:			/* Insert Mode on/off */
1283				vc->vc_decim = on_off;
1284				break;
1285			case 20:		/* Lf, Enter == CrLf/Lf */
1286				if (on_off)
1287					set_kbd(vc, lnm);
1288				else
1289					clr_kbd(vc, lnm);
1290				break;
1291			}
1292		}
1293}
1294
1295/* console_sem is held */
1296static void setterm_command(struct vc_data *vc)
1297{
1298	switch(vc->vc_par[0]) {
1299		case 1:	/* set color for underline mode */
1300			if (vc->vc_can_do_color &&
1301					vc->vc_par[1] < 16) {
1302				vc->vc_ulcolor = color_table[vc->vc_par[1]];
1303				if (vc->vc_underline)
1304					update_attr(vc);
1305			}
1306			break;
1307		case 2:	/* set color for half intensity mode */
1308			if (vc->vc_can_do_color &&
1309					vc->vc_par[1] < 16) {
1310				vc->vc_halfcolor = color_table[vc->vc_par[1]];
1311				if (vc->vc_intensity == 0)
1312					update_attr(vc);
1313			}
1314			break;
1315		case 8:	/* store colors as defaults */
1316			vc->vc_def_color = vc->vc_attr;
1317			if (vc->vc_hi_font_mask == 0x100)
1318				vc->vc_def_color >>= 1;
1319			default_attr(vc);
1320			update_attr(vc);
1321			break;
1322		case 9:	/* set blanking interval */
1323			blankinterval = ((vc->vc_par[1] < 60) ? vc->vc_par[1] : 60) * 60 * HZ;
1324			poke_blanked_console();
1325			break;
1326		case 10: /* set bell frequency in Hz */
1327			if (vc->vc_npar >= 1)
1328				vc->vc_bell_pitch = vc->vc_par[1];
1329			else
1330				vc->vc_bell_pitch = DEFAULT_BELL_PITCH;
1331			break;
1332		case 11: /* set bell duration in msec */
1333			if (vc->vc_npar >= 1)
1334				vc->vc_bell_duration = (vc->vc_par[1] < 2000) ?
1335					vc->vc_par[1] * HZ / 1000 : 0;
1336			else
1337				vc->vc_bell_duration = DEFAULT_BELL_DURATION;
1338			break;
1339		case 12: /* bring specified console to the front */
1340			if (vc->vc_par[1] >= 1 && vc_cons_allocated(vc->vc_par[1] - 1))
1341				set_console(vc->vc_par[1] - 1);
1342			break;
1343		case 13: /* unblank the screen */
1344			poke_blanked_console();
1345			break;
1346		case 14: /* set vesa powerdown interval */
1347			vesa_off_interval = ((vc->vc_par[1] < 60) ? vc->vc_par[1] : 60) * 60 * HZ;
1348			break;
1349		case 15: /* activate the previous console */
1350			set_console(last_console);
1351			break;
1352	}
1353}
1354
1355/* console_sem is held */
1356static void csi_at(struct vc_data *vc, unsigned int nr)
1357{
1358	if (nr > vc->vc_cols - vc->vc_x)
1359		nr = vc->vc_cols - vc->vc_x;
1360	else if (!nr)
1361		nr = 1;
1362	insert_char(vc, nr);
1363}
1364
1365/* console_sem is held */
1366static void csi_L(struct vc_data *vc, unsigned int nr)
1367{
1368	if (nr > vc->vc_rows - vc->vc_y)
1369		nr = vc->vc_rows - vc->vc_y;
1370	else if (!nr)
1371		nr = 1;
1372	scrdown(vc, vc->vc_y, vc->vc_bottom, nr);
1373	vc->vc_need_wrap = 0;
1374}
1375
1376/* console_sem is held */
1377static void csi_P(struct vc_data *vc, unsigned int nr)
1378{
1379	if (nr > vc->vc_cols - vc->vc_x)
1380		nr = vc->vc_cols - vc->vc_x;
1381	else if (!nr)
1382		nr = 1;
1383	delete_char(vc, nr);
1384}
1385
1386/* console_sem is held */
1387static void csi_M(struct vc_data *vc, unsigned int nr)
1388{
1389	if (nr > vc->vc_rows - vc->vc_y)
1390		nr = vc->vc_rows - vc->vc_y;
1391	else if (!nr)
1392		nr=1;
1393	scrup(vc, vc->vc_y, vc->vc_bottom, nr);
1394	vc->vc_need_wrap = 0;
1395}
1396
1397/* console_sem is held (except via vc_init->reset_terminal */
1398static void save_cur(struct vc_data *vc)
1399{
1400	vc->vc_saved_x		= vc->vc_x;
1401	vc->vc_saved_y		= vc->vc_y;
1402	vc->vc_s_intensity	= vc->vc_intensity;
1403	vc->vc_s_underline	= vc->vc_underline;
1404	vc->vc_s_blink		= vc->vc_blink;
1405	vc->vc_s_reverse	= vc->vc_reverse;
1406	vc->vc_s_charset	= vc->vc_charset;
1407	vc->vc_s_color		= vc->vc_color;
1408	vc->vc_saved_G0		= vc->vc_G0_charset;
1409	vc->vc_saved_G1		= vc->vc_G1_charset;
1410}
1411
1412/* console_sem is held */
1413static void restore_cur(struct vc_data *vc)
1414{
1415	gotoxy(vc, vc->vc_saved_x, vc->vc_saved_y);
1416	vc->vc_intensity	= vc->vc_s_intensity;
1417	vc->vc_underline	= vc->vc_s_underline;
1418	vc->vc_blink		= vc->vc_s_blink;
1419	vc->vc_reverse		= vc->vc_s_reverse;
1420	vc->vc_charset		= vc->vc_s_charset;
1421	vc->vc_color		= vc->vc_s_color;
1422	vc->vc_G0_charset	= vc->vc_saved_G0;
1423	vc->vc_G1_charset	= vc->vc_saved_G1;
1424	vc->vc_translate	= set_translate(vc->vc_charset ? vc->vc_G1_charset : vc->vc_G0_charset, vc);
1425	update_attr(vc);
1426	vc->vc_need_wrap = 0;
1427}
1428
1429enum { ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey,
1430	EShash, ESsetG0, ESsetG1, ESpercent, ESignore, ESnonstd,
1431	ESpalette };
1432
1433/* console_sem is held (except via vc_init()) */
1434static void reset_terminal(struct vc_data *vc, int do_clear)
1435{
1436	vc->vc_top		= 0;
1437	vc->vc_bottom		= vc->vc_rows;
1438	vc->vc_state		= ESnormal;
1439	vc->vc_ques		= 0;
1440	vc->vc_translate	= set_translate(LAT1_MAP, vc);
1441	vc->vc_G0_charset	= LAT1_MAP;
1442	vc->vc_G1_charset	= GRAF_MAP;
1443	vc->vc_charset		= 0;
1444	vc->vc_need_wrap	= 0;
1445	vc->vc_report_mouse	= 0;
1446	vc->vc_utf		= 0;
1447	vc->vc_utf_count	= 0;
1448
1449	vc->vc_disp_ctrl	= 0;
1450	vc->vc_toggle_meta	= 0;
1451
1452	vc->vc_decscnm		= 0;
1453	vc->vc_decom		= 0;
1454	vc->vc_decawm		= 1;
1455	vc->vc_deccm		= 1;
1456	vc->vc_decim		= 0;
1457
1458	set_kbd(vc, decarm);
1459	clr_kbd(vc, decckm);
1460	clr_kbd(vc, kbdapplic);
1461	clr_kbd(vc, lnm);
1462	kbd_table[vc->vc_num].lockstate = 0;
1463	kbd_table[vc->vc_num].slockstate = 0;
1464	kbd_table[vc->vc_num].ledmode = LED_SHOW_FLAGS;
1465	kbd_table[vc->vc_num].ledflagstate = kbd_table[vc->vc_num].default_ledflagstate;
1466	/* do not do set_leds here because this causes an endless tasklet loop
1467	   when the keyboard hasn't been initialized yet */
1468
1469	vc->vc_cursor_type = CUR_DEFAULT;
1470	vc->vc_complement_mask = vc->vc_s_complement_mask;
1471
1472	default_attr(vc);
1473	update_attr(vc);
1474
1475	vc->vc_tab_stop[0]	= 0x01010100;
1476	vc->vc_tab_stop[1]	=
1477	vc->vc_tab_stop[2]	=
1478	vc->vc_tab_stop[3]	=
1479	vc->vc_tab_stop[4]	= 0x01010101;
1480
1481	vc->vc_bell_pitch = DEFAULT_BELL_PITCH;
1482	vc->vc_bell_duration = DEFAULT_BELL_DURATION;
1483
1484	gotoxy(vc, 0, 0);
1485	save_cur(vc);
1486	if (do_clear)
1487	    csi_J(vc, 2);
1488}
1489
1490/* console_sem is held */
1491static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
1492{
1493	/*
1494	 *  Control characters can be used in the _middle_
1495	 *  of an escape sequence.
1496	 */
1497	switch (c) {
1498	case 0:
1499		return;
1500	case 7:
1501		if (vc->vc_bell_duration)
1502			kd_mksound(vc->vc_bell_pitch, vc->vc_bell_duration);
1503		return;
1504	case 8:
1505		bs(vc);
1506		return;
1507	case 9:
1508		vc->vc_pos -= (vc->vc_x << 1);
1509		while (vc->vc_x < vc->vc_cols - 1) {
1510			vc->vc_x++;
1511			if (vc->vc_tab_stop[vc->vc_x >> 5] & (1 << (vc->vc_x & 31)))
1512				break;
1513		}
1514		vc->vc_pos += (vc->vc_x << 1);
1515		return;
1516	case 10: case 11: case 12:
1517		lf(vc);
1518		if (!is_kbd(vc, lnm))
1519			return;
1520	case 13:
1521		cr(vc);
1522		return;
1523	case 14:
1524		vc->vc_charset = 1;
1525		vc->vc_translate = set_translate(vc->vc_G1_charset, vc);
1526		vc->vc_disp_ctrl = 1;
1527		return;
1528	case 15:
1529		vc->vc_charset = 0;
1530		vc->vc_translate = set_translate(vc->vc_G0_charset, vc);
1531		vc->vc_disp_ctrl = 0;
1532		return;
1533	case 24: case 26:
1534		vc->vc_state = ESnormal;
1535		return;
1536	case 27:
1537		vc->vc_state = ESesc;
1538		return;
1539	case 127:
1540		del(vc);
1541		return;
1542	case 128+27:
1543		vc->vc_state = ESsquare;
1544		return;
1545	}
1546	switch(vc->vc_state) {
1547	case ESesc:
1548		vc->vc_state = ESnormal;
1549		switch (c) {
1550		case '[':
1551			vc->vc_state = ESsquare;
1552			return;
1553		case ']':
1554			vc->vc_state = ESnonstd;
1555			return;
1556		case '%':
1557			vc->vc_state = ESpercent;
1558			return;
1559		case 'E':
1560			cr(vc);
1561			lf(vc);
1562			return;
1563		case 'M':
1564			ri(vc);
1565			return;
1566		case 'D':
1567			lf(vc);
1568			return;
1569		case 'H':
1570			vc->vc_tab_stop[vc->vc_x >> 5] |= (1 << (vc->vc_x & 31));
1571			return;
1572		case 'Z':
1573			respond_ID(tty);
1574			return;
1575		case '7':
1576			save_cur(vc);
1577			return;
1578		case '8':
1579			restore_cur(vc);
1580			return;
1581		case '(':
1582			vc->vc_state = ESsetG0;
1583			return;
1584		case ')':
1585			vc->vc_state = ESsetG1;
1586			return;
1587		case '#':
1588			vc->vc_state = EShash;
1589			return;
1590		case 'c':
1591			reset_terminal(vc, 1);
1592			return;
1593		case '>':  /* Numeric keypad */
1594			clr_kbd(vc, kbdapplic);
1595			return;
1596		case '=':  /* Appl. keypad */
1597			set_kbd(vc, kbdapplic);
1598			return;
1599		}
1600		return;
1601	case ESnonstd:
1602		if (c=='P') {   /* palette escape sequence */
1603			for (vc->vc_npar = 0; vc->vc_npar < NPAR; vc->vc_npar++)
1604				vc->vc_par[vc->vc_npar] = 0;
1605			vc->vc_npar = 0;
1606			vc->vc_state = ESpalette;
1607			return;
1608		} else if (c=='R') {   /* reset palette */
1609			reset_palette(vc);
1610			vc->vc_state = ESnormal;
1611		} else
1612			vc->vc_state = ESnormal;
1613		return;
1614	case ESpalette:
1615		if ( (c>='0'&&c<='9') || (c>='A'&&c<='F') || (c>='a'&&c<='f') ) {
1616			vc->vc_par[vc->vc_npar++] = (c > '9' ? (c & 0xDF) - 'A' + 10 : c - '0');
1617			if (vc->vc_npar == 7) {
1618				int i = vc->vc_par[0] * 3, j = 1;
1619				vc->vc_palette[i] = 16 * vc->vc_par[j++];
1620				vc->vc_palette[i++] += vc->vc_par[j++];
1621				vc->vc_palette[i] = 16 * vc->vc_par[j++];
1622				vc->vc_palette[i++] += vc->vc_par[j++];
1623				vc->vc_palette[i] = 16 * vc->vc_par[j++];
1624				vc->vc_palette[i] += vc->vc_par[j];
1625				set_palette(vc);
1626				vc->vc_state = ESnormal;
1627			}
1628		} else
1629			vc->vc_state = ESnormal;
1630		return;
1631	case ESsquare:
1632		for (vc->vc_npar = 0; vc->vc_npar < NPAR; vc->vc_npar++)
1633			vc->vc_par[vc->vc_npar] = 0;
1634		vc->vc_npar = 0;
1635		vc->vc_state = ESgetpars;
1636		if (c == '[') { /* Function key */
1637			vc->vc_state=ESfunckey;
1638			return;
1639		}
1640		vc->vc_ques = (c == '?');
1641		if (vc->vc_ques)
1642			return;
1643	case ESgetpars:
1644		if (c == ';' && vc->vc_npar < NPAR - 1) {
1645			vc->vc_npar++;
1646			return;
1647		} else if (c>='0' && c<='9') {
1648			vc->vc_par[vc->vc_npar] *= 10;
1649			vc->vc_par[vc->vc_npar] += c - '0';
1650			return;
1651		} else
1652			vc->vc_state = ESgotpars;
1653	case ESgotpars:
1654		vc->vc_state = ESnormal;
1655		switch(c) {
1656		case 'h':
1657			set_mode(vc, 1);
1658			return;
1659		case 'l':
1660			set_mode(vc, 0);
1661			return;
1662		case 'c':
1663			if (vc->vc_ques) {
1664				if (vc->vc_par[0])
1665					vc->vc_cursor_type = vc->vc_par[0] | (vc->vc_par[1] << 8) | (vc->vc_par[2] << 16);
1666				else
1667					vc->vc_cursor_type = CUR_DEFAULT;
1668				return;
1669			}
1670			break;
1671		case 'm':
1672			if (vc->vc_ques) {
1673				clear_selection();
1674				if (vc->vc_par[0])
1675					vc->vc_complement_mask = vc->vc_par[0] << 8 | vc->vc_par[1];
1676				else
1677					vc->vc_complement_mask = vc->vc_s_complement_mask;
1678				return;
1679			}
1680			break;
1681		case 'n':
1682			if (!vc->vc_ques) {
1683				if (vc->vc_par[0] == 5)
1684					status_report(tty);
1685				else if (vc->vc_par[0] == 6)
1686					cursor_report(vc, tty);
1687			}
1688			return;
1689		}
1690		if (vc->vc_ques) {
1691			vc->vc_ques = 0;
1692			return;
1693		}
1694		switch(c) {
1695		case 'G': case '`':
1696			if (vc->vc_par[0])
1697				vc->vc_par[0]--;
1698			gotoxy(vc, vc->vc_par[0], vc->vc_y);
1699			return;
1700		case 'A':
1701			if (!vc->vc_par[0])
1702				vc->vc_par[0]++;
1703			gotoxy(vc, vc->vc_x, vc->vc_y - vc->vc_par[0]);
1704			return;
1705		case 'B': case 'e':
1706			if (!vc->vc_par[0])
1707				vc->vc_par[0]++;
1708			gotoxy(vc, vc->vc_x, vc->vc_y + vc->vc_par[0]);
1709			return;
1710		case 'C': case 'a':
1711			if (!vc->vc_par[0])
1712				vc->vc_par[0]++;
1713			gotoxy(vc, vc->vc_x + vc->vc_par[0], vc->vc_y);
1714			return;
1715		case 'D':
1716			if (!vc->vc_par[0])
1717				vc->vc_par[0]++;
1718			gotoxy(vc, vc->vc_x - vc->vc_par[0], vc->vc_y);
1719			return;
1720		case 'E':
1721			if (!vc->vc_par[0])
1722				vc->vc_par[0]++;
1723			gotoxy(vc, 0, vc->vc_y + vc->vc_par[0]);
1724			return;
1725		case 'F':
1726			if (!vc->vc_par[0])
1727				vc->vc_par[0]++;
1728			gotoxy(vc, 0, vc->vc_y - vc->vc_par[0]);
1729			return;
1730		case 'd':
1731			if (vc->vc_par[0])
1732				vc->vc_par[0]--;
1733			gotoxay(vc, vc->vc_x ,vc->vc_par[0]);
1734			return;
1735		case 'H': case 'f':
1736			if (vc->vc_par[0])
1737				vc->vc_par[0]--;
1738			if (vc->vc_par[1])
1739				vc->vc_par[1]--;
1740			gotoxay(vc, vc->vc_par[1], vc->vc_par[0]);
1741			return;
1742		case 'J':
1743			csi_J(vc, vc->vc_par[0]);
1744			return;
1745		case 'K':
1746			csi_K(vc, vc->vc_par[0]);
1747			return;
1748		case 'L':
1749			csi_L(vc, vc->vc_par[0]);
1750			return;
1751		case 'M':
1752			csi_M(vc, vc->vc_par[0]);
1753			return;
1754		case 'P':
1755			csi_P(vc, vc->vc_par[0]);
1756			return;
1757		case 'c':
1758			if (!vc->vc_par[0])
1759				respond_ID(tty);
1760			return;
1761		case 'g':
1762			if (!vc->vc_par[0])
1763				vc->vc_tab_stop[vc->vc_x >> 5] &= ~(1 << (vc->vc_x & 31));
1764			else if (vc->vc_par[0] == 3) {
1765				vc->vc_tab_stop[0] =
1766					vc->vc_tab_stop[1] =
1767					vc->vc_tab_stop[2] =
1768					vc->vc_tab_stop[3] =
1769					vc->vc_tab_stop[4] = 0;
1770			}
1771			return;
1772		case 'm':
1773			csi_m(vc);
1774			return;
1775		case 'q': /* DECLL - but only 3 leds */
1776			/* map 0,1,2,3 to 0,1,2,4 */
1777			if (vc->vc_par[0] < 4)
1778				setledstate(kbd_table + vc->vc_num,
1779					    (vc->vc_par[0] < 3) ? vc->vc_par[0] : 4);
1780			return;
1781		case 'r':
1782			if (!vc->vc_par[0])
1783				vc->vc_par[0]++;
1784			if (!vc->vc_par[1])
1785				vc->vc_par[1] = vc->vc_rows;
1786			/* Minimum allowed region is 2 lines */
1787			if (vc->vc_par[0] < vc->vc_par[1] &&
1788			    vc->vc_par[1] <= vc->vc_rows) {
1789				vc->vc_top = vc->vc_par[0] - 1;
1790				vc->vc_bottom = vc->vc_par[1];
1791				gotoxay(vc, 0, 0);
1792			}
1793			return;
1794		case 's':
1795			save_cur(vc);
1796			return;
1797		case 'u':
1798			restore_cur(vc);
1799			return;
1800		case 'X':
1801			csi_X(vc, vc->vc_par[0]);
1802			return;
1803		case '@':
1804			csi_at(vc, vc->vc_par[0]);
1805			return;
1806		case ']': /* setterm functions */
1807			setterm_command(vc);
1808			return;
1809		}
1810		return;
1811	case ESpercent:
1812		vc->vc_state = ESnormal;
1813		switch (c) {
1814		case '@':  /* defined in ISO 2022 */
1815			vc->vc_utf = 0;
1816			return;
1817		case 'G':  /* prelim official escape code */
1818		case '8':  /* retained for compatibility */
1819			vc->vc_utf = 1;
1820			return;
1821		}
1822		return;
1823	case ESfunckey:
1824		vc->vc_state = ESnormal;
1825		return;
1826	case EShash:
1827		vc->vc_state = ESnormal;
1828		if (c == '8') {
1829			/* DEC screen alignment test. kludge :-) */
1830			vc->vc_video_erase_char =
1831				(vc->vc_video_erase_char & 0xff00) | 'E';
1832			csi_J(vc, 2);
1833			vc->vc_video_erase_char =
1834				(vc->vc_video_erase_char & 0xff00) | ' ';
1835			do_update_region(vc, vc->vc_origin, vc->vc_screenbuf_size / 2);
1836		}
1837		return;
1838	case ESsetG0:
1839		if (c == '0')
1840			vc->vc_G0_charset = GRAF_MAP;
1841		else if (c == 'B')
1842			vc->vc_G0_charset = LAT1_MAP;
1843		else if (c == 'U')
1844			vc->vc_G0_charset = IBMPC_MAP;
1845		else if (c == 'K')
1846			vc->vc_G0_charset = USER_MAP;
1847		if (vc->vc_charset == 0)
1848			vc->vc_translate = set_translate(vc->vc_G0_charset, vc);
1849		vc->vc_state = ESnormal;
1850		return;
1851	case ESsetG1:
1852		if (c == '0')
1853			vc->vc_G1_charset = GRAF_MAP;
1854		else if (c == 'B')
1855			vc->vc_G1_charset = LAT1_MAP;
1856		else if (c == 'U')
1857			vc->vc_G1_charset = IBMPC_MAP;
1858		else if (c == 'K')
1859			vc->vc_G1_charset = USER_MAP;
1860		if (vc->vc_charset == 1)
1861			vc->vc_translate = set_translate(vc->vc_G1_charset, vc);
1862		vc->vc_state = ESnormal;
1863		return;
1864	default:
1865		vc->vc_state = ESnormal;
1866	}
1867}
1868
1869/* This is a temporary buffer used to prepare a tty console write
1870 * so that we can easily avoid touching user space while holding the
1871 * console spinlock.  It is allocated in con_init and is shared by
1872 * this code and the vc_screen read/write tty calls.
1873 *
1874 * We have to allocate this statically in the kernel data section
1875 * since console_init (and thus con_init) are called before any
1876 * kernel memory allocation is available.
1877 */
1878char con_buf[CON_BUF_SIZE];
1879DECLARE_MUTEX(con_buf_sem);
1880
1881/* acquires console_sem */
1882static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int count)
1883{
1884#ifdef VT_BUF_VRAM_ONLY
1885#define FLUSH do { } while(0);
1886#else
1887#define FLUSH if (draw_x >= 0) { \
1888	vc->vc_sw->con_putcs(vc, (u16 *)draw_from, (u16 *)draw_to - (u16 *)draw_from, vc->vc_y, draw_x); \
1889	draw_x = -1; \
1890	}
1891#endif
1892
1893	int c, tc, ok, n = 0, draw_x = -1;
1894	unsigned int currcons;
1895	unsigned long draw_from = 0, draw_to = 0;
1896	struct vc_data *vc;
1897	u16 himask, charmask;
1898	const unsigned char *orig_buf = NULL;
1899	int orig_count;
1900
1901	if (in_interrupt())
1902		return count;
1903
1904	might_sleep();
1905
1906	acquire_console_sem();
1907	vc = tty->driver_data;
1908	if (vc == NULL) {
1909		printk(KERN_ERR "vt: argh, driver_data is NULL !\n");
1910		release_console_sem();
1911		return 0;
1912	}
1913
1914	currcons = vc->vc_num;
1915	if (!vc_cons_allocated(currcons)) {
1916	    /* could this happen? */
1917	    static int error = 0;
1918	    if (!error) {
1919		error = 1;
1920		printk("con_write: tty %d not allocated\n", currcons+1);
1921	    }
1922	    release_console_sem();
1923	    return 0;
1924	}
1925	release_console_sem();
1926
1927	orig_buf = buf;
1928	orig_count = count;
1929
1930	/* At this point 'buf' is guaranteed to be a kernel buffer
1931	 * and therefore no access to userspace (and therefore sleeping)
1932	 * will be needed.  The con_buf_sem serializes all tty based
1933	 * console rendering and vcs write/read operations.  We hold
1934	 * the console spinlock during the entire write.
1935	 */
1936
1937	acquire_console_sem();
1938
1939	vc = tty->driver_data;
1940	if (vc == NULL) {
1941		printk(KERN_ERR "vt: argh, driver_data _became_ NULL !\n");
1942		release_console_sem();
1943		goto out;
1944	}
1945
1946	himask = vc->vc_hi_font_mask;
1947	charmask = himask ? 0x1ff : 0xff;
1948
1949	/* undraw cursor first */
1950	if (IS_FG(vc))
1951		hide_cursor(vc);
1952
1953	while (!tty->stopped && count) {
1954		int orig = *buf;
1955		c = orig;
1956		buf++;
1957		n++;
1958		count--;
1959
1960		/* Do no translation at all in control states */
1961		if (vc->vc_state != ESnormal) {
1962			tc = c;
1963		} else if (vc->vc_utf) {
1964		    /* Combine UTF-8 into Unicode */
1965		    /* Incomplete characters silently ignored */
1966		    if(c > 0x7f) {
1967			if (vc->vc_utf_count > 0 && (c & 0xc0) == 0x80) {
1968				vc->vc_utf_char = (vc->vc_utf_char << 6) | (c & 0x3f);
1969				vc->vc_utf_count--;
1970				if (vc->vc_utf_count == 0)
1971				    tc = c = vc->vc_utf_char;
1972				else continue;
1973			} else {
1974				if ((c & 0xe0) == 0xc0) {
1975				    vc->vc_utf_count = 1;
1976				    vc->vc_utf_char = (c & 0x1f);
1977				} else if ((c & 0xf0) == 0xe0) {
1978				    vc->vc_utf_count = 2;
1979				    vc->v

Large files files are truncated, but you can click here to view the full file