patch-2.1.110 linux/drivers/char/console.c
Next file: linux/drivers/char/console_macros.h
Previous file: linux/drivers/char/c-qcam.c
Back to the patch index
Back to the overall index
- Lines: 379
- Date:
Sat Jul 18 13:55:47 1998
- Orig file:
v2.1.109/linux/drivers/char/console.c
- Orig date:
Thu Jul 16 18:09:24 1998
diff -u --recursive --new-file v2.1.109/linux/drivers/char/console.c linux/drivers/char/console.c
@@ -165,15 +165,24 @@
int kmsg_redirect = 0;
/*
+ * 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 = NULL;
+
+/*
* Low-Level Functions
*/
#define IS_FG (currcons == fg_console)
+#define IS_VISIBLE (*display_fg == vc_cons[currcons].d)
#ifdef VT_BUF_VRAM_ONLY
#define DO_UPDATE 0
#else
-#define DO_UPDATE IS_FG
+#define DO_UPDATE IS_VISIBLE
#endif
static inline unsigned short *screenpos(int currcons, int offset, int viewed)
@@ -205,7 +214,7 @@
nr = b - t - 1;
if (b > video_num_lines || t >= b || nr < 1)
return;
- if (IS_FG && sw->con_scroll(vc_cons[currcons].d, t, b, SM_UP, nr))
+ 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));
@@ -224,7 +233,7 @@
nr = b - t - 1;
if (b > video_num_lines || t >= b || nr < 1)
return;
- if (IS_FG && sw->con_scroll(vc_cons[currcons].d, t, b, SM_DOWN, nr))
+ if (IS_VISIBLE && sw->con_scroll(vc_cons[currcons].d, t, b, SM_DOWN, nr))
return;
s = (unsigned short *) (origin+video_size_row*(b-nr-1));
step = video_num_columns * nr;
@@ -401,7 +410,6 @@
}
}
-/* FIXME: Does it make sense to hide cursor on non-fg consoles? */
static inline void hide_cursor(int currcons)
{
sw->con_cursor(vc_cons[currcons].d,CM_ERASE);
@@ -419,7 +427,7 @@
static void set_origin(int currcons)
{
- if (!IS_FG ||
+ if (!IS_VISIBLE ||
!sw->con_set_origin ||
!sw->con_set_origin(vc_cons[currcons].d))
origin = (unsigned long) screenbuf;
@@ -442,9 +450,11 @@
void update_screen(int new_console)
{
int currcons = fg_console;
- int xx, yy, startx, attrib;
+ int redraw = 1;
+ int xx, yy, startx, attrib, old_console;
unsigned short *p, *q;
static int lock = 0;
+ struct vc_data **display;
if (lock)
return;
@@ -457,31 +467,42 @@
clear_selection();
- fg_console = new_console;
- set_origin(currcons);
- currcons = new_console;
- sw->con_cursor (vc_cons[currcons].d, CM_ERASE);
- set_origin(currcons);
- if (sw->con_switch (vc_cons[currcons].d)) {
- /* Update the screen contents */
- p = (unsigned short *)origin;
- attrib = scr_readw(p) & 0xff00;
- for (yy = 0; yy < video_num_lines; yy++) {
- q = p;
- for (startx = xx = 0; xx < video_num_columns; xx++) {
- 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);
+ hide_cursor(currcons);
+ if (fg_console != new_console) {
+ 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)
+ set_origin(currcons);
+ currcons = new_console;
+ if (old_console == new_console)
+ redraw = 0;
+ }
+ if (redraw) {
+ set_origin(currcons);
+ if (sw->con_switch (vc_cons[currcons].d)) {
+ /* Update the screen contents */
+ p = (unsigned short *)origin;
+ attrib = scr_readw(p) & 0xff00;
+ for (yy = 0; yy < video_num_lines; yy++) {
+ q = p;
+ for (startx = xx = 0; xx < video_num_columns; xx++) {
+ 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++;
}
- p++;
+ if (p > q)
+ sw->con_putcs (vc_cons[currcons].d, q,
+ p - q, yy, startx);
}
- if (p > q)
- sw->con_putcs (vc_cons[currcons].d, q,
- p - q, yy, startx);
}
}
set_cursor (currcons);
@@ -504,6 +525,7 @@
/* ++Geert: sw->con_init determines console size */
sw = conswitchp;
cons_num = currcons;
+ display_fg = &master_display_fg;
sw->con_init(vc_cons[currcons].d, 1);
video_size_row = video_num_columns<<1;
video_screen_size = video_num_lines*video_size_row;
@@ -1155,6 +1177,7 @@
update_screen(par[1]-1);
break;
case 13: /* unblank the screen */
+ /* FIXME: call poke_blanked_console? */
unblank_screen();
break;
case 14: /* set vesa powerdown interval */
@@ -1692,6 +1715,12 @@
return 0;
}
+ if (from_user) {
+ /* just to make sure that noone lurks at places he shouldn't see. */
+ if (verify_area(VERIFY_READ, buf, count))
+ return 0; /* ?? are error codes legal here ?? */
+ }
+
/* undraw cursor first */
if (DO_UPDATE)
hide_cursor(currcons);
@@ -1700,12 +1729,6 @@
if (currcons == sel_cons)
clear_selection();
- if (from_user) {
- /* just to make sure that noone lurks at places he shouldn't see. */
- if (verify_area(VERIFY_READ, buf, count))
- return 0; /* ?? are error codes legal here ?? */
- }
-
disable_bh(CONSOLE_BH);
while (count) {
enable_bh(CONSOLE_BH);
@@ -1816,7 +1839,6 @@
}
continue;
}
- /* FIXME: Handle tabs in a special way and use putcs for them as well */
FLUSH
do_con_trol(tty, currcons, c);
}
@@ -1839,6 +1861,7 @@
{
if (want_console >= 0) {
if (want_console != fg_console) {
+ clear_selection();
save_screen();
change_console(want_console);
/* we only changed when the console had already
@@ -2095,12 +2118,9 @@
static void con_flush_chars(struct tty_struct *tty)
{
- unsigned int currcons;
struct vt_struct *vt = (struct vt_struct *)tty->driver_data;
- currcons = vt->vc_num;
- if (vcmode != KD_GRAPHICS)
- set_cursor(currcons);
+ set_cursor(vt->vc_num);
}
/*
@@ -2155,8 +2175,6 @@
* This routine initializes console interrupts, and does nothing
* else. If you want the screen to clear, call tty_write with
* the appropriate escape-sequence.
- *
- * FIXME: return early if we don't _have_ a video card installed.
*/
struct tty_driver console_driver;
@@ -2239,6 +2257,8 @@
}
}
currcons = fg_console = 0;
+ master_display_fg = vc_cons[currcons].d;
+ set_origin(currcons);
save_screen();
gotoxy(currcons,x,y);
csi_J(currcons, 0);
@@ -2260,6 +2280,42 @@
}
/*
+ * If we support more console drivers, this function is used
+ * when a driver wants to take over some existing consoles
+ * and become default driver for newly opened ones.
+ */
+
+#ifndef VT_BUF_VRAM_ONLY
+
+void take_over_console(struct consw *csw, int first, int last, int deflt)
+{
+ int i;
+ const char *desc;
+
+ if (deflt)
+ conswitchp = csw;
+ desc = csw->con_startup();
+ if (!desc) return;
+
+ for (i = first; i <= last; i++) {
+ if (!vc_cons[i].d || !vc_cons[i].d->vc_sw)
+ continue;
+ if (i == fg_console &&
+ vc_cons[i].d->vc_sw->con_save_screen)
+ vc_cons[i].d->vc_sw->con_save_screen(vc_cons[i].d);
+ vc_cons[i].d->vc_sw->con_deinit(vc_cons[i].d);
+ vc_cons[i].d->vc_sw = csw;
+ vc_cons[i].d->vc_sw->con_init(vc_cons[i].d, 0);
+ }
+ printk("Console: switching to %s %s %dx%d\n",
+ vc_cons[fg_console].d->vc_can_do_color ? "colour" : "mono",
+ desc, vc_cons[fg_console].d->vc_cols, vc_cons[fg_console].d->vc_rows);
+ set_palette();
+}
+
+#endif
+
+/*
* Screen blanking
*/
@@ -2273,11 +2329,13 @@
void vesa_blank(void)
{
- vc_cons[fg_console].d->vc_sw->con_blank(vesa_blank_mode + 1);
+ struct vc_data *c = vc_cons[fg_console].d;
+ c->vc_sw->con_blank(c, vesa_blank_mode + 1);
}
void vesa_powerdown(void)
{
+ struct vc_data *c = vc_cons[fg_console].d;
/*
* Power down if currently suspended (1 or 2),
* suspend if currently blanked (0),
@@ -2286,11 +2344,11 @@
*/
switch (vesa_blank_mode) {
case VESA_NO_BLANKING:
- vc_cons[fg_console].d->vc_sw->con_blank(VESA_VSYNC_SUSPEND+1);
+ c->vc_sw->con_blank(c, VESA_VSYNC_SUSPEND+1);
break;
case VESA_VSYNC_SUSPEND:
case VESA_HSYNC_SUSPEND:
- vc_cons[fg_console].d->vc_sw->con_blank(VESA_POWERDOWN+1);
+ c->vc_sw->con_blank(c, VESA_POWERDOWN+1);
break;
}
}
@@ -2305,17 +2363,28 @@
void do_blank_screen(int nopowersave)
{
- int currcons;
+ int currcons = fg_console;
if (console_blanked)
return;
+ /* entering graphics mode? */
+ if (nopowersave) {
+ save_screen();
+ hide_cursor(currcons);
+ sw->con_blank(vc_cons[currcons].d, -1);
+ console_blanked = fg_console + 1;
+ set_origin(currcons);
+ return;
+ }
+
/* don't blank graphics */
if (vt_cons[fg_console]->vc_mode != KD_TEXT) {
console_blanked = fg_console + 1;
- hide_cursor(fg_console);
return;
}
+
+ hide_cursor(fg_console);
if(vesa_off_interval && !nopowersave) {
timer_table[BLANK_TIMER].fn = vesa_powerdown_screen;
timer_table[BLANK_TIMER].expires = jiffies + vesa_off_interval;
@@ -2325,9 +2394,8 @@
timer_table[BLANK_TIMER].fn = unblank_screen;
}
- currcons = fg_console;
save_screen();
- sw->con_blank(1);
+ sw->con_blank(vc_cons[currcons].d, 1);
console_blanked = fg_console + 1;
if(!nopowersave)
@@ -2358,16 +2426,12 @@
currcons = fg_console;
console_blanked = 0;
- if (sw->con_blank(0))
+ if (sw->con_blank(vc_cons[currcons].d, 0))
/* Low-level driver cannot restore -> do it ourselves */
update_screen(fg_console);
set_cursor(fg_console);
}
-/*
- * If a blank_screen is due to a timer, then a power save is allowed.
- * If it is related to console_switching, then avoid vesa_blank().
- */
static void blank_screen(void)
{
do_blank_screen(0);
@@ -2400,7 +2464,7 @@
void set_palette(void)
{
if (vt_cons[fg_console]->vc_mode != KD_GRAPHICS)
- conswitchp->con_set_palette(vc_cons[fg_console].d, color_table);
+ vc_cons[fg_console].d->vc_sw->con_set_palette(vc_cons[fg_console].d, color_table);
}
int set_get_cmap(unsigned char *arg, int set)
@@ -2579,3 +2643,7 @@
EXPORT_SYMBOL(default_blu);
EXPORT_SYMBOL(video_font_height);
EXPORT_SYMBOL(video_scan_lines);
+
+#ifndef VT_BUF_VRAM_ONLY
+EXPORT_SYMBOL(take_over_console);
+#endif
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov