console.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:73k
- /*
- * linux/drivers/char/console.c
- *
- * Copyright (C) 1991, 1992 Linus Torvalds
- */
- /*
- * Hopefully this will be a rather complete VT102 implementation.
- *
- * Beeping thanks to John T Kohl.
- *
- * Virtual Consoles, Screen Blanking, Screen Dumping, Color, Graphics
- * Chars, and VT100 enhancements by Peter MacDonald.
- *
- * Copy and paste function by Andrew Haylett,
- * some enhancements by Alessandro Rubini.
- *
- * Code to check for different video-cards mostly by Galen Hunt,
- * <g-hunt@ee.utah.edu>
- *
- * Rudimentary ISO 10646/Unicode/UTF-8 character set support by
- * Markus Kuhn, <mskuhn@immd4.informatik.uni-erlangen.de>.
- *
- * Dynamic allocation of consoles, aeb@cwi.nl, May 1994
- * Resizing of consoles, aeb, 940926
- *
- * Code for xterm like mouse click reporting by Peter Orbaek 20-Jul-94
- * <poe@daimi.aau.dk>
- *
- * User-defined bell sound, new setterm control sequences and printk
- * redirection by Martin Mares <mj@k332.feld.cvut.cz> 19-Nov-95
- *
- * APM screenblank bug fixed Takashi Manabe <manabe@roy.dsl.tutics.tut.jp>
- *
- * Merge with the abstract console driver by Geert Uytterhoeven
- * <geert@linux-m68k.org>, Jan 1997.
- *
- * Original m68k console driver modifications by
- *
- * - Arno Griffioen <arno@usn.nl>
- * - David Carter <carter@cs.bris.ac.uk>
- *
- * Note that the abstract console driver allows all consoles to be of
- * potentially different sizes, so the following variables depend on the
- * current console (currcons):
- *
- * - video_num_columns
- * - video_num_lines
- * - video_size_row
- * - can_do_color
- *
- * The abstract console driver provides a generic interface for a text
- * console. It supports VGA text mode, frame buffer based graphical consoles
- * and special graphics processors that are only accessible through some
- * registers (e.g. a TMS340x0 GSP).
- *
- * The interface to the hardware is specified using a special structure
- * (struct consw) which contains function pointers to console operations
- * (see <linux/console.h> for more information).
- *
- * Support for changeable cursor shape
- * by Pavel Machek <pavel@atrey.karlin.mff.cuni.cz>, August 1997
- *
- * Ported to i386 and con_scrolldelta fixed
- * by Emmanuel Marty <core@ggi-project.org>, April 1998
- *
- * Resurrected character buffers in videoram plus lots of other trickery
- * by Martin Mares <mj@atrey.karlin.mff.cuni.cz>, July 1998
- *
- * Removed old-style timers, introduced console_timer, made timer
- * deletion SMP-safe. 17Jun00, Andrew Morton <andrewm@uow.edu.au>
- *
- * Removed console_lock, enabled interrupts across all console operations
- * 13 March 2001, Andrew Morton
- *
- * Split out con_write_ctrl_* functions from do_con_write & changed
- * vc_state to function pointer
- * by Russell King <rmk@arm.linux.org.uk>, July 1998
- */
- #define CONSOLE_WIP
- #include <linux/module.h>
- #include <linux/sched.h>
- #include <linux/tty.h>
- #include <linux/tty_flip.h>
- #include <linux/kernel.h>
- #include <linux/string.h>
- #include <linux/errno.h>
- #include <linux/kd.h>
- #include <linux/slab.h>
- #include <linux/major.h>
- #include <linux/mm.h>
- #include <linux/console.h>
- #include <linux/init.h>
- #include <linux/devfs_fs_kernel.h>
- #include <linux/vt_kern.h>
- #include <linux/selection.h>
- #include <linux/console_struct.h>
- #include <linux/kbd_kern.h>
- #include <linux/consolemap.h>
- #include <linux/timer.h>
- #include <linux/interrupt.h>
- #include <linux/config.h>
- #include <linux/version.h>
- #include <linux/tqueue.h>
- #include <linux/bootmem.h>
- #ifdef CONFIG_CONSOLE_PM // bushi
- #include <linux/pm.h>
- #endif
- #include <linux/smp_lock.h>
- #include <asm/io.h>
- #include <asm/system.h>
- #include <asm/uaccess.h>
- #include <asm/bitops.h>
- #include "console_macros.h"
- const struct consw *conswitchp;
- /* A bitmap for codes <32. A bit of 1 indicates that the code
- * corresponding to that bit number invokes some special action
- * (such as cursor movement) and should not be displayed as a
- * glyph unless the disp_ctrl mode is explicitly enabled.
- */
- #define CTRL_ACTION 0x0d00ff81
- #define CTRL_ALWAYS 0x0800f501 /* Cannot be overridden by disp_ctrl */
- /*
- * Here is the default bell parameters: 750HZ, 1/8th of a second
- */
- #define DEFAULT_BELL_PITCH 750
- #define DEFAULT_BELL_DURATION (HZ/8)
- extern void vcs_make_devfs (unsigned int index, int unregister);
- #ifndef MIN
- #define MIN(a,b) ((a) < (b) ? (a) : (b))
- #endif
- static struct tty_struct *console_table[MAX_NR_CONSOLES];
- static struct termios *console_termios[MAX_NR_CONSOLES];
- static struct termios *console_termios_locked[MAX_NR_CONSOLES];
- struct vc vc_cons [MAX_NR_CONSOLES];
- #ifndef VT_SINGLE_DRIVER
- static const struct consw *con_driver_map[MAX_NR_CONSOLES];
- #endif
- static int con_open(struct tty_struct *, struct file *);
- static void vc_init(unsigned int console, unsigned int rows,
- unsigned int cols, int do_clear);
- static void gotoxy(int currcons, int new_x, int new_y);
- static void save_cur(int currcons);
- static void reset_terminal(int currcons, int do_clear);
- static void con_flush_chars(struct tty_struct *tty);
- #ifdef CONFIG_CONSOLE_PM // bushi
- static void blank_screen(unsigned long dummy);
- static void set_vesa_blanking(unsigned long arg);
- static void unblank_screen_t(unsigned long dummy);
- #endif
- static void set_cursor(int currcons);
- static void hide_cursor(int currcons);
- static void console_callback(void *ignored);
- static int printable; /* Is console ready for printing? */
- #ifdef CONFIG_CONSOLE_PM // bushi
- int do_poke_blanked_console;
- int console_blanked;
- static int vesa_blank_mode; /* 0:none 1:suspendV 2:suspendH 3:powerdown */
- static int blankinterval = 10*60*HZ;
- static int vesa_off_interval;
- #endif
- static struct tq_struct console_callback_tq = {
- routine: console_callback,
- };
- /*
- * fg_console is the current virtual console,
- * last_console is the last used one,
- * want_console is the console we want to switch to,
- * kmsg_redirect is the console for kernel messages,
- */
- int fg_console;
- int last_console;
- int want_console = -1;
- int kmsg_redirect;
- /*
- * For each existing display, we have a pointer to console currently visible
- * on that display, allowing consoles other than fg_console to be refreshed
- * appropriately. Unless the low-level driver supplies its own display_fg
- * variable, we use this one for the "master display".
- */
- static struct vc_data *master_display_fg;
- /*
- * Unfortunately, we need to delay tty echo when we're currently writing to the
- * console since the code is (and always was) not re-entrant, so we schedule
- * all flip requests to process context with schedule-task() and run it from
- * console_callback().
- */
- /*
- * For the same reason, we defer scrollback to the console callback.
- */
- static int scrollback_delta;
- #ifdef CONFIG_CONSOLE_PM // bushi
- /*
- * Hook so that the power management routines can (un)blank
- * the console on our behalf.
- */
- int (*console_blank_hook)(int);
- static struct timer_list console_timer;
- #endif
- /*
- * Low-Level Functions
- */
- #define IS_FG (currcons == fg_console)
- #define IS_VISIBLE CON_IS_VISIBLE(vc_cons[currcons].d)
- #ifdef VT_BUF_VRAM_ONLY
- #define DO_UPDATE 0
- #else
- #define DO_UPDATE IS_VISIBLE
- #endif
- #ifdef CONFIG_CONSOLE_PM // bushi
- static int pm_con_request(struct pm_dev *dev, pm_request_t rqst, void *data);
- static struct pm_dev *pm_con;
- #endif
- static inline unsigned short *screenpos(int currcons, int offset, int viewed)
- {
- unsigned short *p;
- if (!viewed)
- p = (unsigned short *)(origin + offset);
- else if (!sw->con_screen_pos)
- p = (unsigned short *)(visible_origin + offset);
- else
- p = sw->con_screen_pos(vc_cons[currcons].d, offset);
- return p;
- }
- static inline void scrolldelta(int lines)
- {
- scrollback_delta += lines;
- schedule_console_callback();
- }
- void schedule_console_callback(void)
- {
- schedule_task(&console_callback_tq);
- }
- static void scrup(int currcons, unsigned int t, unsigned int b, int nr)
- {
- unsigned short *d, *s;
- if (t+nr >= b)
- nr = b - t - 1;
- if (b > video_num_lines || t >= b || nr < 1)
- return;
- if (IS_VISIBLE && sw->con_scroll(vc_cons[currcons].d, t, b, SM_UP, nr))
- return;
- d = (unsigned short *) (origin+video_size_row*t);
- s = (unsigned short *) (origin+video_size_row*(t+nr));
- scr_memcpyw(d, s, (b-t-nr) * video_size_row);
- scr_memsetw(d + (b-t-nr) * video_num_columns, video_erase_char, video_size_row*nr);
- }
- static void
- scrdown(int currcons, unsigned int t, unsigned int b, int nr)
- {
- unsigned short *s;
- unsigned int step;
- if (t+nr >= b)
- nr = b - t - 1;
- if (b > video_num_lines || t >= b || nr < 1)
- return;
- if (IS_VISIBLE && sw->con_scroll(vc_cons[currcons].d, t, b, SM_DOWN, nr))
- return;
- s = (unsigned short *) (origin+video_size_row*t);
- step = video_num_columns * nr;
- scr_memmovew(s + step, s, (b-t-nr)*video_size_row);
- scr_memsetw(s, video_erase_char, 2*step);
- }
- static void do_update_region(int currcons, unsigned long start, int count)
- {
- #ifndef VT_BUF_VRAM_ONLY
- unsigned int xx, yy, offset;
- u16 *p;
- p = (u16 *) start;
- if (!sw->con_getxy) {
- offset = (start - origin) / 2;
- xx = offset % video_num_columns;
- yy = offset / video_num_columns;
- } else {
- int nxx, nyy;
- start = sw->con_getxy(vc_cons[currcons].d, start, &nxx, &nyy);
- xx = nxx; yy = nyy;
- }
- for(;;) {
- u16 attrib = scr_readw(p) & 0xff00;
- int startx = xx;
- u16 *q = p;
- while (xx < video_num_columns && count) {
- if (attrib != (scr_readw(p) & 0xff00)) {
- if (p > q)
- sw->con_putcs(vc_cons[currcons].d, q, p-q, yy, startx);
- startx = xx;
- q = p;
- attrib = scr_readw(p) & 0xff00;
- }
- p++;
- xx++;
- count--;
- }
- if (p > q)
- sw->con_putcs(vc_cons[currcons].d, q, p-q, yy, startx);
- if (!count)
- break;
- xx = 0;
- yy++;
- if (sw->con_getxy) {
- p = (u16 *)start;
- start = sw->con_getxy(vc_cons[currcons].d, start, NULL, NULL);
- }
- }
- #endif
- }
- void update_region(int currcons, unsigned long start, int count)
- {
- if (DO_UPDATE) {
- hide_cursor(currcons);
- do_update_region(currcons, start, count);
- set_cursor(currcons);
- }
- }
- /* Structure of attributes is hardware-dependent */
- static u8 build_attr(int currcons, u8 _color, u8 _intensity, u8 _blink, u8 _underline, u8 _reverse)
- {
- if (sw->con_build_attr)
- return sw->con_build_attr(vc_cons[currcons].d, _color, _intensity, _blink, _underline, _reverse);
- #ifndef VT_BUF_VRAM_ONLY
- /*
- * ++roman: I completely changed the attribute format for monochrome
- * mode (!can_do_color). The formerly used MDA (monochrome display
- * adapter) format didn't allow the combination of certain effects.
- * Now the attribute is just a bit vector:
- * Bit 0..1: intensity (0..2)
- * Bit 2 : underline
- * Bit 3 : reverse
- * Bit 7 : blink
- */
- {
- u8 a = color;
- if (!can_do_color)
- return _intensity |
- (_underline ? 4 : 0) |
- (_reverse ? 8 : 0) |
- (_blink ? 0x80 : 0);
- if (_underline)
- a = (a & 0xf0) | ulcolor;
- else if (_intensity == 0)
- a = (a & 0xf0) | halfcolor;
- if (_reverse)
- a = ((a) & 0x88) | ((((a) >> 4) | ((a) << 4)) & 0x77);
- if (_blink)
- a ^= 0x80;
- if (_intensity == 2)
- a ^= 0x08;
- if (hi_font_mask == 0x100)
- a <<= 1;
- return a;
- }
- #else
- return 0;
- #endif
- }
- static void update_attr(int currcons)
- {
- attr = build_attr(currcons, color, intensity, blink, underline, reverse ^ decscnm);
- video_erase_char = (build_attr(currcons, color, 1, blink, 0, decscnm) << 8) | ' ';
- }
- /* Note: inverting the screen twice should revert to the original state */
- void invert_screen(int currcons, int offset, int count, int viewed)
- {
- unsigned short *p;
- count /= 2;
- p = screenpos(currcons, offset, viewed);
- if (sw->con_invert_region)
- sw->con_invert_region(vc_cons[currcons].d, p, count);
- #ifndef VT_BUF_VRAM_ONLY
- else {
- u16 *q = p;
- int cnt = count;
- u16 a;
- if (!can_do_color) {
- while (cnt--) {
- a = scr_readw(q);
- a ^= 0x0800;
- scr_writew(a, q);
- q++;
- }
- } else if (hi_font_mask == 0x100) {
- while (cnt--) {
- a = scr_readw(q);
- a = ((a) & 0x11ff) | (((a) & 0xe000) >> 4) | (((a) & 0x0e00) << 4);
- scr_writew(a, q);
- q++;
- }
- } else {
- while (cnt--) {
- a = scr_readw(q);
- a = ((a) & 0x88ff) | (((a) & 0x7000) >> 4) | (((a) & 0x0700) << 4);
- scr_writew(a, q);
- q++;
- }
- }
- }
- #endif
- if (DO_UPDATE)
- do_update_region(currcons, (unsigned long) p, count);
- }
- /* used by selection: complement pointer position */
- void complement_pos(int currcons, int offset)
- {
- static unsigned short *p;
- static unsigned short old;
- static unsigned short oldx, oldy;
- if (p) {
- scr_writew(old, p);
- if (DO_UPDATE)
- sw->con_putc(vc_cons[currcons].d, old, oldy, oldx);
- }
- if (offset == -1)
- p = NULL;
- else {
- unsigned short new;
- p = screenpos(currcons, offset, 1);
- old = scr_readw(p);
- new = old ^ complement_mask;
- scr_writew(new, p);
- if (DO_UPDATE) {
- oldx = (offset >> 1) % video_num_columns;
- oldy = (offset >> 1) / video_num_columns;
- sw->con_putc(vc_cons[currcons].d, new, oldy, oldx);
- }
- }
- }
- static void insert_char(int currcons, unsigned int nr)
- {
- unsigned short *p, *q = (unsigned short *) pos;
- p = q + video_num_columns - nr - x;
- while (--p >= q)
- scr_writew(scr_readw(p), p + nr);
- scr_memsetw(q, video_erase_char, nr*2);
- need_wrap = 0;
- if (DO_UPDATE) {
- unsigned short oldattr = attr;
- sw->con_bmove(vc_cons[currcons].d,y,x,y,x+nr,1,
- video_num_columns-x-nr);
- attr = video_erase_char >> 8;
- while (nr--)
- sw->con_putc(vc_cons[currcons].d,
- video_erase_char,y,x+nr);
- attr = oldattr;
- }
- }
- static void delete_char(int currcons, unsigned int nr)
- {
- unsigned int i = x;
- unsigned short *p = (unsigned short *) pos;
- while (++i <= video_num_columns - nr) {
- scr_writew(scr_readw(p+nr), p);
- p++;
- }
- scr_memsetw(p, video_erase_char, nr*2);
- need_wrap = 0;
- if (DO_UPDATE) {
- unsigned short oldattr = attr;
- sw->con_bmove(vc_cons[currcons].d, y, x+nr, y, x, 1,
- video_num_columns-x-nr);
- attr = video_erase_char >> 8;
- while (nr--)
- sw->con_putc(vc_cons[currcons].d,
- video_erase_char, y,
- video_num_columns-1-nr);
- attr = oldattr;
- }
- }
- #ifdef CONFIG_CONSOLE_PM // bushi
- static int softcursor_original;
- static void add_softcursor(int currcons)
- {
- int i = scr_readw((u16 *) pos);
- u32 type = cursor_type;
- if (! (type & 0x10)) return;
- if (softcursor_original != -1) return;
- softcursor_original = i;
- i |= ((type >> 8) & 0xff00 );
- i ^= ((type) & 0xff00 );
- if ((type & 0x20) && ((softcursor_original & 0x7000) == (i & 0x7000))) i ^= 0x7000;
- if ((type & 0x40) && ((i & 0x700) == ((i & 0x7000) >> 4))) i ^= 0x0700;
- scr_writew(i, (u16 *) pos);
- if (DO_UPDATE)
- sw->con_putc(vc_cons[currcons].d, i, y, x);
- }
- #endif
- static void hide_cursor(int currcons)
- {
- if (currcons == sel_cons)
- clear_selection();
- #ifdef CONFIG_CONSOLE_PM // bushi
- if (softcursor_original != -1) {
- scr_writew(softcursor_original,(u16 *) pos);
- if (DO_UPDATE)
- sw->con_putc(vc_cons[currcons].d, softcursor_original, y, x);
- softcursor_original = -1;
- }
- sw->con_cursor(vc_cons[currcons].d,CM_ERASE);
- #endif
- }
- static void set_cursor(int currcons)
- {
- #ifdef CONFIG_CONSOLE_PM // bushi
- if (!IS_FG || console_blanked || vcmode == KD_GRAPHICS)
- return;
- if (deccm) {
- if (currcons == sel_cons)
- clear_selection();
- add_softcursor(currcons);
- if ((cursor_type & 0x0f) != 1)
- sw->con_cursor(vc_cons[currcons].d,CM_DRAW);
- } else
- hide_cursor(currcons);
- #else
- if (!IS_FG || vcmode == KD_GRAPHICS)
- return;
- hide_cursor(currcons);
- #endif
- }
- static void set_origin(int currcons)
- {
- if (!IS_VISIBLE ||
- !sw->con_set_origin ||
- !sw->con_set_origin(vc_cons[currcons].d))
- origin = (unsigned long) screenbuf;
- visible_origin = origin;
- scr_end = origin + screenbuf_size;
- pos = origin + video_size_row*y + 2*x;
- }
- static inline void save_screen(int currcons)
- {
- if (sw->con_save_screen)
- sw->con_save_screen(vc_cons[currcons].d);
- }
- /*
- * Redrawing of screen
- */
- void redraw_screen(int new_console, int is_switch)
- {
- int redraw = 1;
- int currcons, old_console;
- if (!vc_cons_allocated(new_console)) {
- /* strange ... */
- /* printk("redraw_screen: tty %d not allocated ??n", new_console+1); */
- return;
- }
- if (is_switch) {
- currcons = fg_console;
- hide_cursor(currcons);
- if (fg_console != new_console) {
- struct vc_data **display = vc_cons[new_console].d->vc_display_fg;
- old_console = (*display) ? (*display)->vc_num : fg_console;
- *display = vc_cons[new_console].d;
- fg_console = new_console;
- currcons = old_console;
- if (!IS_VISIBLE) {
- save_screen(currcons);
- set_origin(currcons);
- }
- currcons = new_console;
- if (old_console == new_console)
- redraw = 0;
- }
- } else {
- currcons = new_console;
- hide_cursor(currcons);
- }
- if (redraw) {
- int update;
- set_origin(currcons);
- update = sw->con_switch(vc_cons[currcons].d);
- set_palette(currcons);
- if (update && vcmode != KD_GRAPHICS)
- do_update_region(currcons, origin, screenbuf_size/2);
- }
- set_cursor(currcons);
- if (is_switch) {
- set_leds();
- compute_shiftstate();
- }
- }
- /*
- * Allocation, freeing and resizing of VTs.
- */
- int vc_cons_allocated(unsigned int i)
- {
- return (i < MAX_NR_CONSOLES && vc_cons[i].d);
- }
- static void visual_init(int currcons, int init)
- {
- /* ++Geert: sw->con_init determines console size */
- sw = conswitchp;
- #ifndef VT_SINGLE_DRIVER
- if (con_driver_map[currcons])
- sw = con_driver_map[currcons];
- #endif
- cons_num = currcons;
- display_fg = &master_display_fg;
- vc_cons[currcons].d->vc_uni_pagedir_loc = &vc_cons[currcons].d->vc_uni_pagedir;
- vc_cons[currcons].d->vc_uni_pagedir = 0;
- hi_font_mask = 0;
- complement_mask = 0;
- can_do_color = 0;
- sw->con_init(vc_cons[currcons].d, init);
- if (!complement_mask)
- complement_mask = can_do_color ? 0x7700 : 0x0800;
- s_complement_mask = complement_mask;
- video_size_row = video_num_columns<<1;
- screenbuf_size = video_num_lines*video_size_row;
- }
- int vc_allocate(unsigned int currcons) /* return 0 on success */
- {
- if (currcons >= MAX_NR_CONSOLES)
- return -ENXIO;
- if (!vc_cons[currcons].d) {
- long p, q;
- /* prevent users from taking too much memory */
- if (currcons >= MAX_NR_USER_CONSOLES && !capable(CAP_SYS_RESOURCE))
- return -EPERM;
- /* due to the granularity of kmalloc, we waste some memory here */
- /* the alloc is done in two steps, to optimize the common situation
- of a 25x80 console (structsize=216, screenbuf_size=4000) */
- /* although the numbers above are not valid since long ago, the
- point is still up-to-date and the comment still has its value
- even if only as a historical artifact. --mj, July 1998 */
- p = (long) kmalloc(structsize, GFP_KERNEL);
- if (!p)
- return -ENOMEM;
- memset((void *)p, 0, structsize);
- vc_cons[currcons].d = (struct vc_data *)p;
- vt_cons[currcons] = (struct vt_struct *)(p+sizeof(struct vc_data));
- visual_init(currcons, 1);
- if (!*vc_cons[currcons].d->vc_uni_pagedir_loc)
- con_set_default_unimap(currcons);
- q = (long)kmalloc(screenbuf_size, GFP_KERNEL);
- if (!q) {
- kfree((char *) p);
- vc_cons[currcons].d = NULL;
- vt_cons[currcons] = NULL;
- return -ENOMEM;
- }
- screenbuf = (unsigned short *) q;
- kmalloced = 1;
- vc_init(currcons, video_num_lines, video_num_columns, 1);
- #ifdef CONFIG_CONSOLE_PM //bushi
- if (!pm_con) {
- pm_con = pm_register(PM_SYS_DEV,
- PM_SYS_VGA,
- pm_con_request);
- }
- #endif
- }
- return 0;
- }
- /*
- * Change # of rows and columns (0 means unchanged/the size of fg_console)
- * [this is to be used together with some user program
- * like resize that changes the hardware videomode]
- */
- int vc_resize(unsigned int lines, unsigned int cols,
- unsigned int first, unsigned int last)
- {
- unsigned int cc, ll, ss, sr, todo = 0;
- unsigned int currcons = fg_console, i;
- unsigned short *newscreens[MAX_NR_CONSOLES];
- cc = (cols ? cols : video_num_columns);
- ll = (lines ? lines : video_num_lines);
- sr = cc << 1;
- ss = sr * ll;
- for (currcons = first; currcons <= last; currcons++) {
- if (!vc_cons_allocated(currcons) ||
- (cc == video_num_columns && ll == video_num_lines))
- newscreens[currcons] = NULL;
- else {
- unsigned short *p = (unsigned short *) kmalloc(ss, GFP_USER);
- if (!p) {
- for (i = first; i< currcons; i++)
- if (newscreens[i])
- kfree(newscreens[i]);
- return -ENOMEM;
- }
- newscreens[currcons] = p;
- todo++;
- }
- }
- if (!todo)
- return 0;
- for (currcons = first; currcons <= last; currcons++) {
- unsigned int occ, oll, oss, osr;
- unsigned long ol, nl, nlend, rlth, rrem;
- if (!newscreens[currcons] || !vc_cons_allocated(currcons))
- continue;
- oll = video_num_lines;
- occ = video_num_columns;
- osr = video_size_row;
- oss = screenbuf_size;
- video_num_lines = ll;
- video_num_columns = cc;
- video_size_row = sr;
- screenbuf_size = ss;
- rlth = MIN(osr, sr);
- rrem = sr - rlth;
- ol = origin;
- nl = (long) newscreens[currcons];
- nlend = nl + ss;
- if (ll < oll)
- ol += (oll - ll) * osr;
- update_attr(currcons);
- while (ol < scr_end) {
- scr_memcpyw((unsigned short *) nl, (unsigned short *) ol, rlth);
- if (rrem)
- scr_memsetw((void *)(nl + rlth), video_erase_char, rrem);
- ol += osr;
- nl += sr;
- }
- if (nlend > nl)
- scr_memsetw((void *) nl, video_erase_char, nlend - nl);
- if (kmalloced)
- kfree(screenbuf);
- screenbuf = newscreens[currcons];
- kmalloced = 1;
- screenbuf_size = ss;
- set_origin(currcons);
- /* do part of a reset_terminal() */
- top = 0;
- bottom = video_num_lines;
- gotoxy(currcons, x, y);
- save_cur(currcons);
- if (console_table[currcons]) {
- struct winsize ws, *cws = &console_table[currcons]->winsize;
- memset(&ws, 0, sizeof(ws));
- ws.ws_row = video_num_lines;
- ws.ws_col = video_num_columns;
- if ((ws.ws_row != cws->ws_row || ws.ws_col != cws->ws_col) &&
- console_table[currcons]->pgrp > 0)
- kill_pg(console_table[currcons]->pgrp, SIGWINCH, 1);
- *cws = ws;
- }
- if (IS_VISIBLE)
- update_screen(currcons);
- }
- return 0;
- }
- void vc_disallocate(unsigned int currcons)
- {
- acquire_console_sem();
- if (vc_cons_allocated(currcons)) {
- sw->con_deinit(vc_cons[currcons].d);
- if (kmalloced)
- kfree(screenbuf);
- if (currcons >= MIN_NR_CONSOLES)
- kfree(vc_cons[currcons].d);
- vc_cons[currcons].d = NULL;
- }
- release_console_sem();
- }
- /*
- * VT102 emulator
- */
- #define set_kbd(x) set_vc_kbd_mode(kbd_table+currcons,x)
- #define clr_kbd(x) clr_vc_kbd_mode(kbd_table+currcons,x)
- #define is_kbd(x) vc_kbd_mode(kbd_table+currcons,x)
- #define decarm VC_REPEAT
- #define decckm VC_CKMODE
- #define kbdapplic VC_APPLIC
- #define lnm VC_CRLF
- /*
- * this is what the terminal answers to a ESC-Z or csi0c query.
- */
- #define VT100ID "