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. |