Merged from sys/dev/syscons/syscons.c revisions 1.367 and 1.368.

This commit is contained in:
Yoshihiro Takahashi 2001-07-29 10:52:07 +00:00
parent c569c0b5d2
commit 8ea2602a0d

View File

@ -172,6 +172,8 @@ static int do_switch_scr(sc_softc_t *sc, int s);
static int vt_proc_alive(scr_stat *scp);
static int signal_vt_rel(scr_stat *scp);
static int signal_vt_acq(scr_stat *scp);
static int finish_vt_rel(scr_stat *scp, int release, int *s);
static int finish_vt_acq(scr_stat *scp);
static void exchange_scr(sc_softc_t *sc);
static void update_cursor_image(scr_stat *scp);
static int save_kbd_state(scr_stat *scp);
@ -508,18 +510,10 @@ scclose(dev_t dev, int flag, int mode, struct proc *p)
s = spltty();
if ((scp == scp->sc->cur_scp) && (scp->sc->unit == sc_console_unit))
cons_unavail = FALSE;
if (scp->status & SWITCH_WAIT_REL) {
/* assert(scp == scp->sc->cur_scp) */
if (finish_vt_rel(scp, TRUE, &s) == 0) /* force release */
DPRINTF(5, ("reset WAIT_REL, "));
scp->status &= ~SWITCH_WAIT_REL;
do_switch_scr(scp->sc, s);
}
if (scp->status & SWITCH_WAIT_ACQ) {
/* assert(scp == scp->sc->cur_scp) */
if (finish_vt_acq(scp) == 0) /* force acknowledge */
DPRINTF(5, ("reset WAIT_ACQ, "));
scp->status &= ~SWITCH_WAIT_ACQ;
scp->sc->switch_in_progress = 0;
}
#if not_yet_done
if (scp == &main_console) {
scp->pid = 0;
@ -877,18 +871,10 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
if ((scp == sc->cur_scp) && (sc->unit == sc_console_unit))
cons_unavail = FALSE;
/* were we in the middle of the vty switching process? */
if (scp->status & SWITCH_WAIT_REL) {
/* assert(scp == scp->sc->cur_scp) */
if (finish_vt_rel(scp, TRUE, &s) == 0)
DPRINTF(5, ("reset WAIT_REL, "));
scp->status &= ~SWITCH_WAIT_REL;
s = do_switch_scr(sc, s);
}
if (scp->status & SWITCH_WAIT_ACQ) {
/* assert(scp == scp->sc->cur_scp) */
if (finish_vt_acq(scp) == 0)
DPRINTF(5, ("reset WAIT_ACQ, "));
scp->status &= ~SWITCH_WAIT_ACQ;
sc->switch_in_progress = 0;
}
} else {
if (!ISSIGVALID(mode->relsig) || !ISSIGVALID(mode->acqsig)
|| !ISSIGVALID(mode->frsig)) {
@ -930,32 +916,17 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
error = EINVAL;
switch(*(int *)data) {
case VT_FALSE: /* user refuses to release screen, abort */
if ((scp == sc->old_scp) && (scp->status & SWITCH_WAIT_REL)) {
sc->old_scp->status &= ~SWITCH_WAIT_REL;
sc->switch_in_progress = 0;
if ((error = finish_vt_rel(scp, FALSE, &s)) == 0)
DPRINTF(5, ("sc%d: VT_FALSE\n", sc->unit));
error = 0;
}
break;
case VT_TRUE: /* user has released screen, go on */
if ((scp == sc->old_scp) && (scp->status & SWITCH_WAIT_REL)) {
scp->status &= ~SWITCH_WAIT_REL;
s = do_switch_scr(sc, s);
if ((error = finish_vt_rel(scp, TRUE, &s)) == 0)
DPRINTF(5, ("sc%d: VT_TRUE\n", sc->unit));
error = 0;
}
break;
case VT_ACKACQ: /* acquire acknowledged, switch completed */
if ((scp == sc->new_scp) && (scp->status & SWITCH_WAIT_ACQ)) {
scp->status &= ~SWITCH_WAIT_ACQ;
sc->switch_in_progress = 0;
if ((error = finish_vt_acq(scp)) == 0)
DPRINTF(5, ("sc%d: VT_ACKACQ\n", sc->unit));
error = 0;
}
break;
default:
break;
}
@ -973,22 +944,22 @@ scioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
return EINVAL;
case VT_ACTIVATE: /* switch to screen *data */
i = (*(int *)data == 0) ? scp->index : (*(int *)data - 1);
s = spltty();
sc_clean_up(sc->cur_scp);
splx(s);
return sc_switch_scr(sc, *(int *)data - 1);
return sc_switch_scr(sc, i);
case VT_WAITACTIVE: /* wait for switch to occur */
if ((*(int *)data >= sc->first_vty + sc->vtys)
|| (*(int *)data < sc->first_vty))
i = (*(int *)data == 0) ? scp->index : (*(int *)data - 1);
if ((i < sc->first_vty) || (i >= sc->first_vty + sc->vtys))
return EINVAL;
s = spltty();
error = sc_clean_up(sc->cur_scp);
splx(s);
if (error)
return error;
if (*(int *)data != 0)
scp = SC_STAT(SC_DEV(sc, *(int *)data - 1));
scp = SC_STAT(SC_DEV(sc, i));
if (scp == scp->sc->cur_scp)
return 0;
while ((error=tsleep((caddr_t)&scp->smode, PZERO|PCATCH,
@ -2098,6 +2069,7 @@ sc_touch_scrn_saver(void)
int
sc_switch_scr(sc_softc_t *sc, u_int next_scr)
{
scr_stat *cur_scp;
struct tty *tp;
struct proc *p;
int s;
@ -2114,13 +2086,14 @@ sc_switch_scr(sc_softc_t *sc, u_int next_scr)
}
s = spltty();
cur_scp = sc->cur_scp;
/* we are in the middle of the vty switching process... */
if (sc->switch_in_progress
&& (sc->cur_scp->smode.mode == VT_PROCESS)
&& sc->cur_scp->proc) {
p = pfind(sc->cur_scp->pid);
if (sc->cur_scp->proc != p) {
&& (cur_scp->smode.mode == VT_PROCESS)
&& cur_scp->proc) {
p = pfind(cur_scp->pid);
if (cur_scp->proc != p) {
if (p)
PROC_UNLOCK(p);
/*
@ -2129,23 +2102,21 @@ sc_switch_scr(sc_softc_t *sc, u_int next_scr)
* are not reset here yet; they will be cleared later.
*/
DPRINTF(5, ("cur_scp controlling process %d died, ",
sc->cur_scp->pid));
if (sc->cur_scp->status & SWITCH_WAIT_REL) {
cur_scp->pid));
if (cur_scp->status & SWITCH_WAIT_REL) {
/*
* Force the previous switch to finish, but return now
* with error.
*/
DPRINTF(5, ("reset WAIT_REL, "));
sc->cur_scp->status &= ~SWITCH_WAIT_REL;
s = do_switch_scr(sc, s);
finish_vt_rel(cur_scp, TRUE, &s);
splx(s);
DPRINTF(5, ("finishing previous switch\n"));
return EINVAL;
} else if (sc->cur_scp->status & SWITCH_WAIT_ACQ) {
} else if (cur_scp->status & SWITCH_WAIT_ACQ) {
/* let's assume screen switch has been completed. */
DPRINTF(5, ("reset WAIT_ACQ, "));
sc->cur_scp->status &= ~SWITCH_WAIT_ACQ;
sc->switch_in_progress = 0;
finish_vt_acq(cur_scp);
} else {
/*
* We are in between screen release and acquisition, and
@ -2163,13 +2134,13 @@ sc_switch_scr(sc_softc_t *sc, u_int next_scr)
* The following code is a gross kludge to cope with this
* problem for which there is no clean solution. XXX
*/
if (sc->cur_scp->status & SWITCH_WAIT_REL) {
if (cur_scp->status & SWITCH_WAIT_REL) {
switch (sc->switch_in_progress++) {
case 1:
break;
case 2:
DPRINTF(5, ("sending relsig again, "));
signal_vt_rel(sc->cur_scp);
signal_vt_rel(cur_scp);
break;
case 3:
break;
@ -2180,19 +2151,18 @@ sc_switch_scr(sc_softc_t *sc, u_int next_scr)
* VT_FALSE.
*/
DPRINTF(5, ("force reset WAIT_REL, "));
sc->cur_scp->status &= ~SWITCH_WAIT_REL;
sc->switch_in_progress = 0;
finish_vt_rel(cur_scp, FALSE, &s);
splx(s);
DPRINTF(5, ("act as if VT_FALSE was seen\n"));
return EINVAL;
}
} else if (sc->cur_scp->status & SWITCH_WAIT_ACQ) {
} else if (cur_scp->status & SWITCH_WAIT_ACQ) {
switch (sc->switch_in_progress++) {
case 1:
break;
case 2:
DPRINTF(5, ("sending acqsig again, "));
signal_vt_acq(sc->cur_scp);
signal_vt_acq(cur_scp);
break;
case 3:
break;
@ -2200,8 +2170,7 @@ sc_switch_scr(sc_softc_t *sc, u_int next_scr)
default:
/* clear the flag and finish the previous switch */
DPRINTF(5, ("force reset WAIT_ACQ, "));
sc->cur_scp->status &= ~SWITCH_WAIT_ACQ;
sc->switch_in_progress = 0;
finish_vt_acq(cur_scp);
break;
}
}
@ -2215,7 +2184,7 @@ sc_switch_scr(sc_softc_t *sc, u_int next_scr)
if ((next_scr < sc->first_vty) || (next_scr >= sc->first_vty + sc->vtys)
|| sc->switch_in_progress) {
splx(s);
sc_bell(sc->cur_scp, bios_value.bell_pitch, BELL_DURATION);
sc_bell(cur_scp, bios_value.bell_pitch, BELL_DURATION);
DPRINTF(5, ("error 1\n"));
return EINVAL;
}
@ -2225,13 +2194,13 @@ sc_switch_scr(sc_softc_t *sc, u_int next_scr)
* if the switch mode is VT_AUTO, unless the next vty is the same
* as the current or the current vty has been closed (but showing).
*/
tp = VIRTUAL_TTY(sc, sc->cur_scp->index);
if ((sc->cur_scp->index != next_scr)
tp = VIRTUAL_TTY(sc, cur_scp->index);
if ((cur_scp->index != next_scr)
&& ISTTYOPEN(tp)
&& (sc->cur_scp->smode.mode == VT_AUTO)
&& ISGRAPHSC(sc->cur_scp)) {
&& (cur_scp->smode.mode == VT_AUTO)
&& ISGRAPHSC(cur_scp)) {
splx(s);
sc_bell(sc->cur_scp, bios_value.bell_pitch, BELL_DURATION);
sc_bell(cur_scp, bios_value.bell_pitch, BELL_DURATION);
DPRINTF(5, ("error, graphics mode\n"));
return EINVAL;
}
@ -2246,7 +2215,7 @@ sc_switch_scr(sc_softc_t *sc, u_int next_scr)
tp = VIRTUAL_TTY(sc, next_scr);
if (!ISTTYOPEN(tp)) {
splx(s);
sc_bell(sc->cur_scp, bios_value.bell_pitch, BELL_DURATION);
sc_bell(cur_scp, bios_value.bell_pitch, BELL_DURATION);
DPRINTF(5, ("error 2, requested vty isn't open!\n"));
return EINVAL;
}
@ -2260,7 +2229,7 @@ sc_switch_scr(sc_softc_t *sc, u_int next_scr)
/* this is the start of vty switching process... */
++sc->switch_in_progress;
sc->delayed_next_scr = 0;
sc->old_scp = sc->cur_scp;
sc->old_scp = cur_scp;
sc->new_scp = SC_STAT(SC_DEV(sc, next_scr));
if (sc->new_scp == sc->old_scp) {
sc->switch_in_progress = 0;
@ -2369,6 +2338,31 @@ signal_vt_acq(scr_stat *scp)
return TRUE;
}
static int
finish_vt_rel(scr_stat *scp, int release, int *s)
{
if (scp == scp->sc->old_scp && scp->status & SWITCH_WAIT_REL) {
scp->status &= ~SWITCH_WAIT_REL;
if (release)
*s = do_switch_scr(scp->sc, *s);
else
scp->sc->switch_in_progress = 0;
return 0;
}
return EINVAL;
}
static int
finish_vt_acq(scr_stat *scp)
{
if (scp == scp->sc->new_scp && scp->status & SWITCH_WAIT_ACQ) {
scp->status &= ~SWITCH_WAIT_ACQ;
scp->sc->switch_in_progress = 0;
return 0;
}
return EINVAL;
}
static void
exchange_scr(sc_softc_t *sc)
{