|
From: <jsi...@us...> - 2007-04-14 23:31:35
|
Revision: 2373
http://linuxconsole.svn.sourceforge.net/linuxconsole/?rev=2373&view=rev
Author: jsimmons
Date: 2007-04-14 16:31:33 -0700 (Sat, 14 Apr 2007)
Log Message:
-----------
merged to 2.6.21. Missing the new sysfs. Need to merge to what we have
Modified Paths:
--------------
branches/ruby-2.6.21/ruby-2.6/drivers/char/vc_screen.c
branches/ruby-2.6.21/ruby-2.6/drivers/char/vt.c
branches/ruby-2.6.21/ruby-2.6/drivers/char/vt_ioctl.c
Modified: branches/ruby-2.6.21/ruby-2.6/drivers/char/vc_screen.c
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/drivers/char/vc_screen.c 2007-04-11 20:19:34 UTC (rev 2372)
+++ branches/ruby-2.6.21/ruby-2.6/drivers/char/vc_screen.c 2007-04-14 23:31:33 UTC (rev 2373)
@@ -52,6 +52,7 @@
void putconsxy(struct vc_data *vc, unsigned char *p)
{
+ hide_cursor(vc);
gotoxy(vc, p[0], p[1]);
set_cursor(vc);
}
Modified: branches/ruby-2.6.21/ruby-2.6/drivers/char/vt.c
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/drivers/char/vt.c 2007-04-11 20:19:34 UTC (rev 2372)
+++ branches/ruby-2.6.21/ruby-2.6/drivers/char/vt.c 2007-04-14 23:31:33 UTC (rev 2373)
@@ -72,6 +72,13 @@
*
* Removed console_lock, enabled interrupts across all console operations
* 13 March 2001, Andrew Morton
+ *
+ * Fixed UTF-8 mode so alternate charset modes always work according
+ * to control sequences interpreted in do_con_trol function
+ * preserving backward VT100 semigraphics compatibility,
+ * malformed UTF sequences represented as sequences of replacement glyphs,
+ * original codes or '?' as a last resort if replacement glyph is undefined
+ * by Adam Tla/lka <at...@pg...>, Aug 2006
*/
#include <linux/module.h>
@@ -87,14 +94,12 @@
#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/tiocl.h>
#include <linux/consolemap.h>
#include <linux/timer.h>
#include <linux/interrupt.h>
-#include <linux/config.h>
#include <linux/workqueue.h>
#include <linux/bootmem.h>
#include <linux/pm.h>
@@ -113,8 +118,6 @@
#define CTRL_ACTION 0x0d00ff81
#define CTRL_ALWAYS 0x0800f501 /* Cannot be overridden by disp_ctrl */
-extern void vcs_make_devfs(struct tty_struct *tty);
-extern void vcs_remove_devfs(struct tty_struct *tty);
extern void console_map_init(void);
#ifdef CONFIG_VGA_CONSOLE
@@ -677,19 +680,24 @@
void complement_pos(struct vc_data *vc, int offset)
{
static unsigned short oldx, oldy, old;
- static unsigned short *p;
+ static int old_offset = -1;
WARN_CONSOLE_UNLOCKED();
- if (p) {
- scr_writew(old, p);
+ if (old_offset != -1 && old_offset >= 0 &&
+ old_offset < vc->vc_screenbuf_size) {
+ scr_writew(old, screenpos(vc, old_offset, 1));
if (DO_UPDATE)
sw->con_putc(vc, old, oldy, oldx);
}
- if (offset == -1)
- p = NULL;
- else {
+
+ old_offset = offset;
+
+ if (offset != -1 && offset >= 0 &&
+ offset < vc->vc_screenbuf_size) {
unsigned short new;
+ unsigned short *p;
+
p = screenpos(vc, offset, 1);
old = scr_readw(p);
new = old ^ vc->vc_complement_mask;
@@ -738,7 +746,7 @@
if (vt->vt_blanked) {
if (vt->blank_state == blank_vesa_wait) {
vt->blank_state = blank_off;
- powerdown_screen((unsigned long)vt);
+ vc->vc_sw->con_blank(vc, vesa_blank_mode + 1, 0);
}
return;
}
@@ -768,14 +776,14 @@
save_screen(vc);
/* In case we need to reset origin, blanking hook returns 1 */
- i = sw->con_blank(vc, 1, 0);
+ i = sw->con_blank(vc, vesa_off_interval ? 1 : (vesa_blank_mode + 1), 0);
vt->vt_blanked = 1;
if (i)
set_origin(vc);
if (console_blank_hook && console_blank_hook(1))
return;
- if (vt->off_interval) {
+ if (vt->off_interval && vt->blank_mode) {
vt->blank_state = blank_vesa_wait;
mod_timer(&vt->timer, jiffies + vt->off_interval);
}
@@ -785,9 +793,9 @@
EXPORT_SYMBOL(do_blank_screen);
/*
- * We defer the timer blanking to work queue so it can take the console semaphore
+ * We defer the timer blanking to work queue so it can take the console mutex
* (console operations can still happen at irq time, but only from printk which
- * has the console semaphore. Not perfect yet, but better than no locking
+ * has the console mutex. Not perfect yet, but better than no locking
*/
static void blank_screen_t(unsigned long dummy)
{
@@ -874,9 +882,9 @@
* with other console code and prevention of re-entrancy is
* ensured with the console semaphore.
*/
-static void vt_callback(void *private)
+static void vt_callback(struct work_struct *work)
{
- struct vt_struct *vt = (struct vt_struct *) private;
+ struct vt_struct *vt = container_of(work, struct vt_struct, SAK_work);
if (!vt || !vt->want_vc || !vt->want_vc->vc_tty)
return;
@@ -908,10 +916,24 @@
release_console_sem();
}
-inline void set_console(struct vc_data *vc)
+int set_console(struct vc_data *vc)
{
+ if (!vc || vc->display_fg->vt_dont_switch ||
+ (vc->vt_mode.mode == VT_AUTO && vc->vc_mode == KD_GRAPHICS)) {
+
+ /*
+ * Console switch will fail in console_callback() or
+ * change_console() so there is no point scheduling
+ * the callback
+ *
+ * Existing set_console() users don't check the return
+ * value so this shouldn't break anything
+ */
+ return -EINVAL;
+ }
vc->display_fg->want_vc = vc;
schedule_work(&vc->display_fg->vt_work);
+ return 0;
}
/*
@@ -1003,6 +1025,7 @@
vc->vc_num = currcons;
vc->display_fg = vt;
+ INIT_WORK(&vc->SAK_work, vc_SAK);
visual_init(vc, 1);
if (vt->kmalloced || !((vt->first_vc) == currcons)) {
vc->vc_screenbuf = (unsigned short *) kmalloc(vc->vc_screenbuf_size, GFP_KERNEL);
@@ -1029,14 +1052,26 @@
return vc;
}
-int vc_disallocate(struct vc_data *vc)
+int vc_lock_resize(struct vc_data *vc, unsigned int cols, unsigned int lines)
{
+ int rc;
+
+ acquire_console_sem();
+ rc = vc_resize(vc, cols, lines);
+ release_console_sem();
+ return rc;
+}
+
+int vc_deallocate(struct vc_data *vc)
+{
struct vt_struct *vt = vc->display_fg;
WARN_CONSOLE_UNLOCKED();
if (vc && vc->vc_num > MIN_NR_CONSOLES) {
sw->con_deinit(vc);
+ put_pid(vc->vt_pid);
+ module_put(sw->owner);
vt->vc_cons[vc->vc_num - vt->first_vc] = NULL;
if (vt->kmalloced)
kfree(screenbuf);
@@ -1071,15 +1106,16 @@
int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines)
{
- unsigned int old_cols, old_rows, old_screenbuf_size, old_row_size;
- unsigned long ol, nl, nlend, rlth, rrem;
- unsigned int new_cols, new_rows, ss, new_row_size, err = 0;
+ unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0;
+ unsigned int old_cols, old_rows, old_row_size, old_screen_size;
+ unsigned int new_cols, new_rows, new_row_size, new_screen_size;
+ unsigned int end;
unsigned short *newscreen;
WARN_CONSOLE_UNLOCKED();
if (!vc)
- return 0;
+ return -ENXIO;
if (cols > VC_RESIZE_MAXCOL || lines > VC_RESIZE_MAXROW)
return -EINVAL;
@@ -1087,23 +1123,22 @@
new_cols = (cols ? cols : vc->vc_cols);
new_rows = (lines ? lines : vc->vc_rows);
new_row_size = new_cols << 1;
- ss = new_row_size * new_rows;
+ new_screen_size = new_row_size * new_rows;
if (new_cols == vc->vc_cols && new_rows == vc->vc_rows)
return 0;
- newscreen = (unsigned short *) kmalloc(ss, GFP_USER);
+ newscreen = kmalloc(new_screen_size, GFP_USER);
if (!newscreen)
return -ENOMEM;
old_rows = vc->vc_rows;
old_cols = vc->vc_cols;
old_row_size = vc->vc_size_row;
- old_screenbuf_size = vc->vc_screenbuf_size;
+ old_screen_size = vc->vc_screenbuf_size;
err = resize_screen(vc, new_cols, new_rows);
if (err) {
- resize_screen(vc, old_cols, old_rows);
kfree(newscreen);
return err;
}
@@ -1111,32 +1146,57 @@
vc->vc_rows = new_rows;
vc->vc_cols = new_cols;
vc->vc_size_row = new_row_size;
- vc->vc_screenbuf_size = ss;
+ vc->vc_screenbuf_size = new_screen_size;
rlth = min(old_row_size, new_row_size);
rrem = new_row_size - rlth;
- ol = vc->vc_origin;
- nl = (long) newscreen;
- nlend = nl + ss;
- if (new_rows < old_rows)
- ol += (old_rows - new_rows) * old_row_size;
+ old_origin = vc->vc_origin;
+ new_origin = (long) newscreen;
+ new_scr_end = new_origin + new_screen_size;
+ if (vc->vc_y > new_rows) {
+ if (old_rows - vc->vc_y < new_rows) {
+ /*
+ * Cursor near the bottom, copy contents from the
+ * bottom of buffer
+ */
+ old_origin += (old_rows - new_rows) * old_row_size;
+ end = vc->vc_scr_end;
+ } else {
+ /*
+ * Cursor is in no man's land, copy 1/2 screenful
+ * from the top and bottom of cursor position
+ */
+ old_origin += (vc->vc_y - new_rows/2) * old_row_size;
+ end = old_origin + (old_row_size * new_rows);
+ }
+ } else
+ /*
+ * Cursor near the top, copy contents from the top of buffer
+ */
+ end = (old_rows > new_rows) ? old_origin +
+ (old_row_size * new_rows) :
+ vc->vc_scr_end;
+
update_attr(vc);
- while (ol < vc->vc_scr_end) {
- scr_memcpyw((unsigned short *) nl, (unsigned short *) ol, rlth);
+ while (old_origin < end) {
+ scr_memcpyw((unsigned short *) new_origin,
+ (unsigned short *) old_origin, rlth);
if (rrem)
- scr_memsetw((void *)(nl + rlth), vc->vc_video_erase_char, rrem);
- ol += old_row_size;
- nl += new_row_size;
+ scr_memsetw((void *)(new_origin + rlth),
+ vc->vc_video_erase_char, rrem);
+ old_origin += old_row_size;
+ new_origin += new_row_size;
}
- if (nlend > nl)
- scr_memsetw((void *) nl, vc->vc_video_erase_char, nlend - nl);
+ if (new_scr_end > new_origin)
+ scr_memsetw((void *)new_origin, vc->vc_video_erase_char,
+ new_scr_end - new_origin);
if (vc->display_fg->kmalloced)
kfree(vc->vc_screenbuf);
vc->vc_screenbuf = newscreen;
vc->display_fg->kmalloced = 1;
- vc->vc_screenbuf_size = ss;
+ vc->vc_screenbuf_size = new_screen_size;
set_origin(vc);
/* do part of a reset_terminal() */
@@ -1153,8 +1213,8 @@
ws.ws_col = vc->vc_cols;
ws.ws_ypixel = vc->vc_scan_lines;
if ((ws.ws_row != cws->ws_row || ws.ws_col != cws->ws_col) &&
- vc->vc_tty->pgrp > 0)
- kill_pg(vc->vc_tty->pgrp, SIGWINCH, 1);
+ vc->vc_tty->pgrp)
+ kill_pgrp(vc->vc_tty->pgrp, SIGWINCH, 1);
*cws = ws;
}
@@ -1163,6 +1223,16 @@
return 0;
}
+int vc_lock_resize(struct vc_data *vc, unsigned int cols, unsigned int lines)
+{
+ int rc;
+
+ acquire_console_sem();
+ rc = vc_resize(vc, cols, lines);
+ release_console_sem();
+ return rc;
+}
+
void vc_SAK(struct work_struct *work)
{
struct vc *vc_con =
@@ -1273,17 +1343,23 @@
/* Do no translation at all in control states */
if (!vc->vc_state) {
tc = c;
- } else if (vc->vc_utf) {
+ } else if (vc->vc_utf && !vc->vc_disp_ctrl) {
/* Combine UTF-8 into Unicode */
- /* Incomplete characters silently ignored */
+ /* Malformed sequences as sequences of replacement glyphs */
+rescan_last_byte:
if(c > 0x7f) {
- if (vc->vc_utf_count > 0 && (c & 0xc0) == 0x80) {
- vc->vc_utf_char = (vc->vc_utf_char << 6) | (c & 0x3f);
- vc->vc_utf_count--;
- if (vc->vc_utf_count == 0)
- tc = c = vc->vc_utf_char;
- else continue;
+ if (vc->vc_utf_count > 0)
+ if ((c & 0xc0) == 0x80) {
+ vc->vc_utf_char = (vc->vc_utf_char << 6) | (c & 0x3f);
+ if (--vc->vc_utf_count) {
+ vc->vc_npar++;
+ continue;
+ }
+ tc = c = vc->vc_utf_char;
+ else
+ goto replacement;
} else {
+ vc->vc_npar = 0;
if ((c & 0xe0) == 0xc0) {
vc->vc_utf_count = 1;
vc->vc_utf_char = (c & 0x1f);
@@ -1300,15 +1376,16 @@
vc->vc_utf_count = 5;
vc->vc_utf_char = (c & 0x01);
} else
- vc->vc_utf_count = 0;
+ goto replacement_glyph;
continue;
}
} else {
+ if (vc->vc_utf_count)
+ goto replacement_glyph;
tc = c;
- vc->vc_utf_count = 0;
}
- } else { /* no utf */
- tc = vc->vc_translate[vc->vc_toggle_meta ? (c|0x80) : c];
+ } else { /* no utf or alternate charset mode */
+ tc = vc->vc_translate[vc->vc_toggle_meta ? (c | 0x80) : c];
}
/* If the original code was a control character we
@@ -1322,31 +1399,33 @@
* direct-to-font zone in UTF-8 mode.
*/
ok = tc && (c >= 32 ||
- (!vc->vc_utf && !(((vc->vc_disp_ctrl ? CTRL_ALWAYS
- : CTRL_ACTION) >> c) & 1)))
+ !(vc->vc_disp_ctrl ? (CTRL_ALWAYS >> c) & 1 :
+ vc->vc_utf || ((CTRL_ACTION >> c) & 1)))
&& (c != 127 || vc->vc_disp_ctrl)
&& (c != 128+27);
if (!vc->vc_state && ok) {
/* Now try to find out how to display it */
tc = conv_uni_to_pc(vc, tc);
- if ( tc == -4 ) {
+ if (tc & ~charmask) {
+ if ( tc == -4 ) {
/* If we got -4 (not found) then see if we have
defined a replacement character (U+FFFD) */
- tc = conv_uni_to_pc(vc, 0xfffd);
-
- /* One reason for the -4 can be that we just
- did a clear_unimap();
- try at least to show something. */
- if (tc == -4)
- tc = c;
- } else if ( tc == -3 ) {
- /* Bad hash table -- hope for the best */
- tc = c;
+replacement_glyph:
+ tc = conv_uni_to_pc(vc, 0xfffd);
+ if (!(tc & ~charmask))
+ goto display_glyph;
+ } else if ( tc != -3 )
+ continue; /* nothing to display */
+ /* no hash table or no replacement --
+ * hope for the best */
+ if ( c & ~charmask )
+ tc = '?';
+ else
+ tc = c;
}
- if (tc & ~charmask)
- continue; /* Conversion failed */
+display_glyph:
if (vc->vc_need_wrap || vc->vc_irm)
FLUSH
if (vc->vc_need_wrap) {
@@ -1368,6 +1447,15 @@
vc->vc_x++;
draw_to = (vc->vc_pos += 2);
}
+ if (vc->vc_utf_count) {
+ if (vc->vc_npar) {
+ vc->vc_npar--;
+ goto display_glyph;
+ }
+ vc->vc_utf_count = 0;
+ c = orig;
+ goto rescan_last_byte;
+ }
continue;
}
FLUSH
@@ -1376,6 +1464,8 @@
FLUSH
console_conditional_schedule();
release_console_sem();
+
+out:
return n;
#undef FLUSH
}
@@ -1390,7 +1480,7 @@
struct vc_data *vc = tty->driver_data;
int ret = 0;
- if (tty->count == 1) {
+ if (tty->driver_data == NULL) {
acquire_console_sem();
ret = tty->index;
vc = vc_allocate(ret);
@@ -1402,7 +1492,7 @@
tty->winsize.ws_row = vc->vc_rows;
tty->winsize.ws_col = vc->vc_cols;
}
- vcs_make_devfs(tty);
+ vcs_make_sysfs(tty);
}
release_console_sem();
}
@@ -1410,15 +1500,15 @@
}
/*
- * We take tty_sem in here to prevent another thread from coming in via init_dev
+ * We take tty_mutex in here to prevent another thread from coming in via init_dev
* and taking a ref against the tty while we're in the process of forgetting
* about it and cleaning things up.
*
- * This is because vcs_remove_devfs() can sleep and will drop the BKL.
+ * This is because vcs_remove_sysfs() can sleep and will drop the BKL.
*/
static void vt_close(struct tty_struct *tty, struct file * filp)
{
- down(&tty_sem);
+ mutex_lock(&tty_mutex);
acquire_console_sem();
if (tty && tty->count == 1) {
struct vc_data *vc = tty->driver_data;
@@ -1426,16 +1516,16 @@
vc->vc_tty = NULL;
tty->driver_data = NULL;
release_console_sem();
- vcs_remove_devfs(tty);
- up(&tty_sem);
+ vcs_remove_sysfs(tty);
+ mutex_unlock(&tty_mutex);
/*
- * tty_sem is released, but we still hold BKL, so there is
+ * tty_mutex is released, but we still hold BKL, so there is
* still exclusion against init_dev()
*/
return;
}
release_console_sem();
- up(&tty_sem);
+ mutex_unlock(&tty_mutex);
}
static int vt_write(struct tty_struct * tty, const unsigned char *buf, int count)
@@ -1676,7 +1766,9 @@
ret = paste_selection(tty);
break;
case TIOCL_UNBLANKSCREEN:
+ acquire_console_sem();
unblank_screen();
+ release_console_sem();
break;
case TIOCL_SELLOADLUT:
ret = sel_loadlut(p);
@@ -1701,6 +1793,10 @@
return -EFAULT;
vc->display_fg->blank_mode = (data < 4) ? data : 0;
break;
+ case TIOCL_GETKMSGREDIRECT:
+ data = kmsg_redirect;
+ ret = __put_user(data, p);
+ break;
case TIOCL_SETKMSGREDIRECT:
if (!capable(CAP_SYS_ADMIN)) {
ret = -EPERM;
@@ -1723,8 +1819,10 @@
}
break;
case TIOCL_BLANKSCREEN: /* until explicitly unblanked, not only poked */
+ acquire_console_sem();
ignore_poke = 1;
do_blank_screen(vc->display_fg, 0);
+ release_console_sem();
break;
case TIOCL_BLANKEDSCREEN:
ret = vc->display_fg->vt_blanked;
@@ -1822,7 +1920,7 @@
console_initcall(vt_console_init);
-static struct tty_operations vt_ops = {
+static const struct tty_operations vt_ops = {
.open = vt_open,
.close = vt_close,
.write = vt_write,
@@ -1848,7 +1946,6 @@
if (!console_driver)
panic("Couldn't allocate VT console driver\n");
console_driver->owner = THIS_MODULE;
- console_driver->devfs_name = "vc/";
console_driver->name = "tty";
console_driver->name_base = 1;
console_driver->major = TTY_MAJOR;
@@ -1881,14 +1978,13 @@
* and become default driver for newly opened ones.
*/
-int take_over_console(struct vt_struct *vt, const struct consw *csw)
+static int bind_vt_driver(struct vt_struct *vt, const struct consw *csw)
{
struct vc_data *vc = vt->fg_console;
- struct module *owner;
- const char *desc;
+ struct module *owner = csw->owner;
+ const char *desc = NULL;
int i;
- owner = csw->owner;
if (!try_module_get(owner))
return -ENODEV;
@@ -1930,7 +2026,9 @@
vc->vc_visible_origin = vc->vc_origin;
vc->vc_scr_end = vc->vc_origin + vc->vc_screenbuf_size;
vc->vc_pos = vc->vc_origin + vc->vc_size_rows * vc->vc_y + 2 * vc->vc_x;
+ INIT_WORK(&vc->SAK_work, vc_SAK);
visual_init(vc, 0);
+ set_origin(vc);
update_attr(vc);
/* If the console changed between mono <-> color, then
@@ -1962,6 +2060,7 @@
EXPORT_SYMBOL(default_grn);
EXPORT_SYMBOL(default_blu);
EXPORT_SYMBOL(vc_resize);
+EXPORT_SYMBOL(vc_lock_resize);
EXPORT_SYMBOL(console_blank_hook);
EXPORT_SYMBOL(vt_list);
EXPORT_SYMBOL(take_over_console);
Modified: branches/ruby-2.6.21/ruby-2.6/drivers/char/vt_ioctl.c
===================================================================
--- branches/ruby-2.6.21/ruby-2.6/drivers/char/vt_ioctl.c 2007-04-11 20:19:34 UTC (rev 2372)
+++ branches/ruby-2.6.21/ruby-2.6/drivers/char/vt_ioctl.c 2007-04-14 23:31:33 UTC (rev 2373)
@@ -236,7 +236,7 @@
ret = -ENOMEM;
goto reterr;
}
-
+
/* we mostly copy too much here (512bytes), but who cares ;) */
if (copy_from_user(kbs, user_kdgkb, sizeof(struct kbsentry))) {
ret = -EFAULT;
@@ -254,9 +254,9 @@
if (p)
for ( ; *p && sz; p++, sz--)
if (put_user(*p, up++)) {
- ret = -EFAULT;
+ ret = -EFAULT;
goto reterr;
- }
+ }
if (put_user('\0', up)) {
ret = -EFAULT;
goto reterr;
@@ -271,7 +271,7 @@
q = func_table[i];
first_free = funcbufptr + (funcbufsize - funcbufleft);
for (j = i + 1; j < MAX_NR_FUNC && !func_table[j]; j++);
-
+
if (j < MAX_NR_FUNC)
fj = func_table[j];
else
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|