patch-2.1.31 linux/drivers/char/vt.c
Next file: linux/drivers/char/wdt.c
Previous file: linux/drivers/char/tty_io.c
Back to the patch index
Back to the overall index
- Lines: 234
- Date:
Thu Mar 27 14:36:39 1997
- Orig file:
v2.1.30/linux/drivers/char/vt.c
- Orig date:
Thu Mar 27 14:40:03 1997
diff -u --recursive --new-file v2.1.30/linux/drivers/char/vt.c linux/drivers/char/vt.c
@@ -29,7 +29,7 @@
#include "diacr.h"
#include "selection.h"
-extern char vt_dont_switch;
+char vt_dont_switch = 0;
extern struct tty_driver console_driver;
#define VT_IS_IN_USE(i) (console_driver.table[i] && console_driver.table[i]->count)
@@ -80,6 +80,7 @@
extern int con_set_cmap(unsigned char *cmap);
extern int con_get_cmap(unsigned char *cmap);
extern void reset_palette(int currcons);
+extern void set_palette(void) ;
extern int con_adjust_height(unsigned long fontheight);
extern int video_mode_512ch;
@@ -1143,3 +1144,216 @@
return -ENOIOCTLCMD;
}
}
+
+/*
+ * Sometimes we want to wait until a particular VT has been activated. We
+ * do it in a very simple manner. Everybody waits on a single queue and
+ * get woken up at once. Those that are satisfied go on with their business,
+ * while those not ready go back to sleep. Seems overkill to add a wait
+ * to each vt just for this - usually this does nothing!
+ */
+static struct wait_queue *vt_activate_queue = NULL;
+
+/*
+ * Sleeps until a vt is activated, or the task is interrupted. Returns
+ * 0 if activation, -EINTR if interrupted.
+ */
+int vt_waitactive(int vt)
+{
+ int retval;
+ struct wait_queue wait = { current, NULL };
+
+ add_wait_queue(&vt_activate_queue, &wait);
+ for (;;) {
+ current->state = TASK_INTERRUPTIBLE;
+ retval = 0;
+ if (vt == fg_console)
+ break;
+ retval = -EINTR;
+ if (current->signal & ~current->blocked)
+ break;
+ schedule();
+ }
+ remove_wait_queue(&vt_activate_queue, &wait);
+ current->state = TASK_RUNNING;
+ return retval;
+}
+
+#define vt_wake_waitactive() wake_up(&vt_activate_queue)
+
+void reset_vc(unsigned int new_console)
+{
+ vt_cons[new_console]->vc_mode = KD_TEXT;
+ kbd_table[new_console].kbdmode = VC_XLATE;
+ vt_cons[new_console]->vt_mode.mode = VT_AUTO;
+ vt_cons[new_console]->vt_mode.waitv = 0;
+ vt_cons[new_console]->vt_mode.relsig = 0;
+ vt_cons[new_console]->vt_mode.acqsig = 0;
+ vt_cons[new_console]->vt_mode.frsig = 0;
+ vt_cons[new_console]->vt_pid = -1;
+ vt_cons[new_console]->vt_newvt = -1;
+ reset_palette (new_console) ;
+}
+
+/*
+ * Performs the back end of a vt switch
+ */
+void complete_change_console(unsigned int new_console)
+{
+ unsigned char old_vc_mode;
+
+ if ((new_console == fg_console) || (vt_dont_switch))
+ return;
+ if (!vc_cons_allocated(new_console))
+ return;
+ last_console = fg_console;
+
+ /*
+ * If we're switching, we could be going from KD_GRAPHICS to
+ * KD_TEXT mode or vice versa, which means we need to blank or
+ * unblank the screen later.
+ */
+ old_vc_mode = vt_cons[fg_console]->vc_mode;
+ update_screen(new_console);
+
+ /*
+ * If this new console is under process control, send it a signal
+ * telling it that it has acquired. Also check if it has died and
+ * clean up (similar to logic employed in change_console())
+ */
+ if (vt_cons[new_console]->vt_mode.mode == VT_PROCESS)
+ {
+ /*
+ * Send the signal as privileged - kill_proc() will
+ * tell us if the process has gone or something else
+ * is awry
+ */
+ if (kill_proc(vt_cons[new_console]->vt_pid,
+ vt_cons[new_console]->vt_mode.acqsig,
+ 1) != 0)
+ {
+ /*
+ * The controlling process has died, so we revert back to
+ * normal operation. In this case, we'll also change back
+ * to KD_TEXT mode. I'm not sure if this is strictly correct
+ * but it saves the agony when the X server dies and the screen
+ * remains blanked due to KD_GRAPHICS! It would be nice to do
+ * this outside of VT_PROCESS but there is no single process
+ * to account for and tracking tty count may be undesirable.
+ */
+ reset_vc(new_console);
+ }
+ }
+
+ /*
+ * We do this here because the controlling process above may have
+ * gone, and so there is now a new vc_mode
+ */
+ if (old_vc_mode != vt_cons[new_console]->vc_mode)
+ {
+ if (vt_cons[new_console]->vc_mode == KD_TEXT)
+ do_unblank_screen();
+ else
+ do_blank_screen(1);
+ }
+
+ /* Set the colour palette for this VT */
+ if (vt_cons[new_console]->vc_mode == KD_TEXT)
+ set_palette() ;
+
+#ifdef CONFIG_SUN_CONSOLE
+ if (old_vc_mode != vt_cons[new_console]->vc_mode)
+ {
+ extern void set_cursor(int currcons);
+ extern void hide_cursor(void);
+
+ if (old_vc_mode == KD_GRAPHICS)
+ {
+ extern void sun_clear_margin(void);
+ extern void render_screen(void);
+
+ sun_clear_margin();
+ render_screen();
+ set_cursor(fg_console);
+ }
+ else
+ hide_cursor();
+ }
+#endif
+ /*
+ * Wake anyone waiting for their VT to activate
+ */
+ vt_wake_waitactive();
+ return;
+}
+
+/*
+ * Performs the front-end of a vt switch
+ */
+void change_console(unsigned int new_console)
+{
+ if ((new_console == fg_console) || (vt_dont_switch))
+ return;
+ if (!vc_cons_allocated(new_console))
+ return;
+
+ /*
+ * If this vt is in process mode, then we need to handshake with
+ * that process before switching. Essentially, we store where that
+ * vt wants to switch to and wait for it to tell us when it's done
+ * (via VT_RELDISP ioctl).
+ *
+ * We also check to see if the controlling process still exists.
+ * If it doesn't, we reset this vt to auto mode and continue.
+ * This is a cheap way to track process control. The worst thing
+ * that can happen is: we send a signal to a process, it dies, and
+ * the switch gets "lost" waiting for a response; hopefully, the
+ * user will try again, we'll detect the process is gone (unless
+ * the user waits just the right amount of time :-) and revert the
+ * vt to auto control.
+ */
+ if (vt_cons[fg_console]->vt_mode.mode == VT_PROCESS)
+ {
+ /*
+ * Send the signal as privileged - kill_proc() will
+ * tell us if the process has gone or something else
+ * is awry
+ */
+ if (kill_proc(vt_cons[fg_console]->vt_pid,
+ vt_cons[fg_console]->vt_mode.relsig,
+ 1) == 0)
+ {
+ /*
+ * It worked. Mark the vt to switch to and
+ * return. The process needs to send us a
+ * VT_RELDISP ioctl to complete the switch.
+ */
+ vt_cons[fg_console]->vt_newvt = new_console;
+ return;
+ }
+
+ /*
+ * The controlling process has died, so we revert back to
+ * normal operation. In this case, we'll also change back
+ * to KD_TEXT mode. I'm not sure if this is strictly correct
+ * but it saves the agony when the X server dies and the screen
+ * remains blanked due to KD_GRAPHICS! It would be nice to do
+ * this outside of VT_PROCESS but there is no single process
+ * to account for and tracking tty count may be undesirable.
+ */
+ reset_vc(fg_console);
+
+ /*
+ * Fall through to normal (VT_AUTO) handling of the switch...
+ */
+ }
+
+ /*
+ * Ignore all switches in KD_GRAPHICS+VT_AUTO mode
+ */
+ if (vt_cons[fg_console]->vc_mode == KD_GRAPHICS)
+ return;
+
+ complete_change_console(new_console);
+}
+
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov