summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>2001-01-22 18:48:45 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>2001-01-22 18:48:45 +0000
commitbb6ebc6cc193723db4f253080cbda504ae9776fd (patch)
tree8514b3d243aaadf5e5b922beafe72546e07c0500
parentf81208f15d5644ca56925c2b34cc57aade008815 (diff)
keyboard led update lockup patch; pr 1432, smat@acm.org
-rw-r--r--sys/arch/i386/isa/pcvt/pcvt_ext.c22
-rw-r--r--sys/arch/i386/isa/pcvt/pcvt_hdr.h4
-rw-r--r--sys/arch/i386/isa/pcvt/pcvt_kbd.c98
-rw-r--r--sys/arch/i386/isa/pcvt/pcvt_out.c10
-rw-r--r--sys/arch/i386/isa/pcvt/pcvt_vtf.c10
5 files changed, 102 insertions, 42 deletions
diff --git a/sys/arch/i386/isa/pcvt/pcvt_ext.c b/sys/arch/i386/isa/pcvt/pcvt_ext.c
index babde2b9990..1f125296ed1 100644
--- a/sys/arch/i386/isa/pcvt/pcvt_ext.c
+++ b/sys/arch/i386/isa/pcvt/pcvt_ext.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pcvt_ext.c,v 1.28 2000/10/07 03:12:45 aaron Exp $ */
+/* $OpenBSD: pcvt_ext.c,v 1.29 2001/01/22 18:48:43 deraadt Exp $ */
/*
* Copyright (c) 1992, 1995 Hellmuth Michaelis and Joerg Wunsch.
*
@@ -2319,8 +2319,23 @@ switch_screen(int n, int oldgrafx, int newgrafx)
if(!newgrafx)
{
- update_led(); /* update led's */
-
+ /*
+ * update_led() was moved to vgapage() because switching
+ * from X with kbd leds on under heavy IO (e.g. cd /; ls -R
+ * in an XTerm) to a VT caused kbd lockup.
+ * The following remaining problems will be solved later:
+ * 1. killing X under heavy IO as above, with leds on,
+ * still causes kbd lockup
+ * 2. starting X takes the led state from the first VT, and
+ * not from the VT where startx is executed
+ * 3. switching back and forth between X and VTs causes some
+ * mismatch in the kbd led state
+ * grep update_led in the pcvt sources to see where
+ * Mathias Schmocker <smat@acm.org>, 27 Nov. 2000
+ */
+#if 0
+ update_led(1); /* update led's */
+#endif
/* if we switch to a vt with force 24 lines mode and */
/* pure VT emulation and 25 rows charset, then we have */
/* to clear the last line on display ... */
@@ -2491,6 +2506,7 @@ vgapage(int new_screen)
/* we are committed */
vt_switch_pending = 0;
reallocate_scrollbuffer(vsp, scrollback_pages);
+ update_led(1); /* was in switch_screen() before */
}
}
return 0;
diff --git a/sys/arch/i386/isa/pcvt/pcvt_hdr.h b/sys/arch/i386/isa/pcvt/pcvt_hdr.h
index 0cfd7b19332..dc0fdb829f6 100644
--- a/sys/arch/i386/isa/pcvt/pcvt_hdr.h
+++ b/sys/arch/i386/isa/pcvt/pcvt_hdr.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pcvt_hdr.h,v 1.43 2000/12/21 16:54:53 aaron Exp $ */
+/* $OpenBSD: pcvt_hdr.h,v 1.44 2001/01/22 18:48:43 deraadt Exp $ */
/*
* Copyright (c) 1992, 1995 Hellmuth Michaelis and Joerg Wunsch.
@@ -1029,7 +1029,7 @@ void toggl_awm ( struct video_state *svsp );
void toggl_bell ( struct video_state *svsp );
void toggl_columns ( struct video_state *svsp );
void toggl_sevenbit ( struct video_state *svsp );
-void update_led ( void );
+void update_led ( u_char cause );
void vga10_vga10 ( u_char *invga, u_char *outvga );
void vga10_vga14 ( u_char *invga, u_char *outvga );
void vga10_vga16 ( u_char *invga, u_char *outvga );
diff --git a/sys/arch/i386/isa/pcvt/pcvt_kbd.c b/sys/arch/i386/isa/pcvt/pcvt_kbd.c
index e3b7897a227..deb157f6bc2 100644
--- a/sys/arch/i386/isa/pcvt/pcvt_kbd.c
+++ b/sys/arch/i386/isa/pcvt/pcvt_kbd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pcvt_kbd.c,v 1.39 2000/10/16 02:25:22 aaron Exp $ */
+/* $OpenBSD: pcvt_kbd.c,v 1.40 2001/01/22 18:48:43 deraadt Exp $ */
/*
* Copyright (c) 1992, 1995 Hellmuth Michaelis and Joerg Wunsch.
@@ -76,9 +76,11 @@
#include "vt.h"
/* #if NVT > 0 */
+#include <sys/ttydefaults.h> /* CSTOP, CSTART for XON/XOFF scrlck emul. */
#include "pcvt_hdr.h" /* global include */
#define LEDSTATE_UPDATE_PENDING (1 << 3)
+#define LEDSTATE_UPDATING (1 << 4)
static void fkey1(void), fkey2(void), fkey3(void), fkey4(void);
static void fkey5(void), fkey6(void), fkey7(void), fkey8(void);
@@ -168,6 +170,7 @@ do_vgapage(int page)
* in the interest of robustness. It may be possible that interrupts
* get lost other times as well.
*/
+ /* Previous comment obsolete, update_led() now interrupt driven */
struct timeout kbd_led_intr_to;
@@ -187,22 +190,35 @@ check_for_lost_intr (void *arg)
* update keyboard led's
*---------------------------------------------------------------------------*/
void
-update_led(void)
+update_led(u_char cause)
{
#if !PCVT_NO_LED_UPDATE
/* Don't update LED's unless necessary. */
- int opri, new_ledstate, response1, response2;
+ int opri, new_ledstate;
+
+ if (!keyboard_type) return; /* allow disconnected kbd operation */
opri = spltty();
new_ledstate = ((vsp->scroll_lock) | (vsp->num_lock * 2) |
(vsp->caps_lock * 4));
-
+#if 0
if (new_ledstate != ledstate) {
- ledstate = LEDSTATE_UPDATE_PENDING;
-
- if (kbd_cmd(KEYB_C_LEDS) != 0) {
- printf("pcvt: kbd led cmd timeout\n");
+#endif /* because of switch_screen() and vgapage() changes */
+ if ((cause == KBD_SCROLL) || (cause == KBD_NUM) ||
+ (cause == KBD_CAPS) ||
+ ((cause == 1) && (!do_initialization)) ||
+ ((cause == 2) && (!do_initialization)) ||
+ ((cause == KEYB_R_RESEND) &&
+ (ledstate == LEDSTATE_UPDATE_PENDING))) {
+
+ if (kbd_cmd(KEYB_C_LEDS) != 0) {
+ printf("pcvt: kbd led cmd timeout\n");
+ goto bail;
+ }
+ ledstate = LEDSTATE_UPDATE_PENDING;
+ if (cause == KEYB_R_RESEND)
+ printf("pcvt: kbd led cmd resend\n");
goto bail;
}
@@ -227,25 +243,36 @@ update_led(void)
* reconnects. The keyboard hardware is very simple and
* well designed :-).
*/
- response1 = kbd_response();
+ /*
+ * Previous comment obsolete, update_led() now interrupt driven
+ */
- if (kbd_cmd(new_ledstate) != 0) {
- printf("pcvt: kbd led data timeout\n");
+ if (((cause == KEYB_R_ACK) &&
+ (ledstate == LEDSTATE_UPDATE_PENDING)) ||
+ ((cause == KEYB_R_RESEND) &&
+ (ledstate == LEDSTATE_UPDATING))) {
+
+ if (kbd_cmd(new_ledstate) != 0) {
+ printf("pcvt: kbd led data timeout\n");
+ goto bail;
+ }
+ ledstate = LEDSTATE_UPDATING;
+ if (cause == KEYB_R_RESEND)
+ printf("pcvt:kbd led data resend\n");
goto bail;
}
- response2 = kbd_response();
- if (response1 == KEYB_R_ACK && response2 == KEYB_R_ACK)
+ if ((cause == KEYB_R_ACK) && (ledstate == LEDSTATE_UPDATING)) {
ledstate = new_ledstate;
- else {
- printf("pcvt: kbd led cmd not ack'd (resp %#x %#x)\n",
- response1, response2);
+ goto bail;
}
#if PCVT_UPDLED_LOSES_INTR
timeout_add(&kbd_led_intr_to, hz);
#endif /* PCVT_UPDLED_LOSES_INTR */
+#if 0
}
+#endif /* because of switch_screen() and vgapage() changes */
bail:
splx(opri);
#endif /* !PCVT_NO_LED_UPDATE */
@@ -883,7 +910,7 @@ xlatkey2ascii(U_short key)
more_chars = (u_char *)"\033OP"; /* PF1 */
else {
vsp->num_lock ^= 1;
- update_led();
+ update_led(KBD_NUM);
}
return (more_chars);
@@ -941,9 +968,7 @@ sgetc(int noblock)
u_char *cp, dt, key;
u_short type;
static u_char kbd_lastkey = 0; /* last keystroke */
-#ifdef XSERVER
static char keybuf[2] = {0}; /* the second 0 is a delimiter! */
-#endif /* XSERVER */
static struct {
u_char extended: 1; /* extended prefix seen */
@@ -991,6 +1016,10 @@ loop:
dt = inb(CONTROLLER_DATA); /* yes, get data */
#endif /* !PCVT_KBD_FIFO */
+
+ if ((dt == KEYB_R_ACK) || (dt == KEYB_R_RESEND))
+ update_led(dt); /* handle ACK/NACK correctly in X */
+
/*
* If x mode is active, only care for locking keys, then
* return the scan code instead of any key translation.
@@ -1048,15 +1077,17 @@ loop:
/* lets look what we got */
switch (dt) {
+ case KEYB_R_ACK: /* acknowledge after command has rx'd*/
+ case KEYB_R_RESEND: /* keyboard wants us to resend cmnd */
+ update_led(dt); /* handle ACK/NACK correctly, no X */
+ break;
case KEYB_R_OVERRUN0: /* keyboard buffer overflow */
#if PCVT_SCANSET == 2
case KEYB_R_SELFOK: /* keyboard selftest ok */
#endif /* PCVT_SCANSET == 2 */
case KEYB_R_ECHO: /* keyboard response to KEYB_C_ECHO */
- case KEYB_R_ACK: /* acknowledge after command has rx'd*/
case KEYB_R_SELFBAD: /* keyboard selftest FAILED */
case KEYB_R_DIAGBAD: /* keyboard self diagnostic failure */
- case KEYB_R_RESEND: /* keyboard wants us to resend cmnd */
case KEYB_R_OVERRUN1: /* keyboard buffer overflow */
break;
@@ -1295,6 +1326,7 @@ scroll_reset:
type &= KBD_MASK;
+ keybuf[0] = 0;
switch (type) {
case KBD_SHFTLOCK:
if (!kbd_status.breakseen && key != kbd_lastkey)
@@ -1304,17 +1336,19 @@ scroll_reset:
case KBD_CAPS:
if (!kbd_status.breakseen && key != kbd_lastkey) {
vsp->caps_lock ^= 1;
- update_led();
+ update_led(KBD_CAPS);
}
break;
case KBD_SCROLL:
if (!kbd_status.breakseen && key != kbd_lastkey) {
vsp->scroll_lock ^= 1;
- update_led();
+ update_led(KBD_SCROLL);
if (!(vsp->scroll_lock))
- wakeup((caddr_t)&(vsp->scroll_lock));
+ keybuf[0] = CSTART;
+ else
+ keybuf[0] = CSTOP;
}
break;
@@ -1349,6 +1383,16 @@ scroll_reset:
cp = xlatkey2ascii(key); /* have a key */
+ if (cp) /* link ^S/^Q to scrlck led */
+ if (((*cp == CSTOP) && (!vsp->scroll_lock)) ||
+ ((*cp == CSTART) && (vsp->scroll_lock))) {
+ vsp->scroll_lock ^= 1;
+ update_led(KBD_SCROLL);
+ }
+
+ if (keybuf[0]) /* XON/XOFF scrlck emul. */
+ cp = (u_char *)keybuf;
+
if (cp == NULL && !noblock)
goto loop;
@@ -1364,7 +1408,7 @@ setlockkeys(int snc)
vsp->scroll_lock = snc & 1;
vsp->num_lock = (snc & 2) ? 1 : 0;
vsp->caps_lock = (snc & 4) ? 1 : 0;
- update_led();
+ update_led(1);
}
/*---------------------------------------------------------------------------*
@@ -1610,7 +1654,7 @@ void
vt_keynum(struct video_state *svsp)
{
svsp->num_lock = 1;
- update_led();
+ update_led(1);
}
/*---------------------------------------------------------------------------*
@@ -1620,7 +1664,7 @@ void
vt_keyappl(struct video_state *svsp)
{
svsp->num_lock = 0;
- update_led();
+ update_led(1);
}
/*---------------------------------------------------------------------------*
diff --git a/sys/arch/i386/isa/pcvt/pcvt_out.c b/sys/arch/i386/isa/pcvt/pcvt_out.c
index e982b70dbf9..8a8a23cfc80 100644
--- a/sys/arch/i386/isa/pcvt/pcvt_out.c
+++ b/sys/arch/i386/isa/pcvt/pcvt_out.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pcvt_out.c,v 1.29 2000/10/16 03:38:28 aaron Exp $ */
+/* $OpenBSD: pcvt_out.c,v 1.30 2001/01/22 18:48:44 deraadt Exp $ */
/*
* Copyright (c) 1992, 1995 Hellmuth Michaelis and Joerg Wunsch.
@@ -1218,7 +1218,7 @@ vt_coldinit(void)
/* update keyboard led's */
- update_led();
+ update_led(1);
}
/*---------------------------------------------------------------------------*
@@ -1327,6 +1327,12 @@ check_scroll(struct video_state *svsp)
svsp->cur_offset -= svsp->maxcol;/* update position */
+ if ((svsp->scroll_lock) && (switch_page == -1))
+ { /* remove scrlck */
+ svsp->scroll_lock ^= 1; /* CSTART,CSTOP */
+ update_led(KBD_SCROLL); /* XON/XOFF emul. */
+ }
+
if(switch_page != -1) /* someone wanted to switch ? */
{
vgapage(switch_page); /* yes, then switch ! */
diff --git a/sys/arch/i386/isa/pcvt/pcvt_vtf.c b/sys/arch/i386/isa/pcvt/pcvt_vtf.c
index 850f91682e4..83854f3f89a 100644
--- a/sys/arch/i386/isa/pcvt/pcvt_vtf.c
+++ b/sys/arch/i386/isa/pcvt/pcvt_vtf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pcvt_vtf.c,v 1.17 2000/12/21 16:54:54 aaron Exp $ */
+/* $OpenBSD: pcvt_vtf.c,v 1.18 2001/01/22 18:48:44 deraadt Exp $ */
/*
* Copyright (c) 1992, 1995 Hellmuth Michaelis and Joerg Wunsch.
@@ -557,7 +557,7 @@ vt_str(struct video_state *svsp)
svsp->selchar = 0; /* selective attribute off */
vt_initsel(svsp);
- update_led(); /* update keyboard LED's */
+ update_led(2); /* update keyboard LED's */
}
/*---------------------------------------------------------------------------*
@@ -2012,9 +2012,6 @@ roll_up(struct video_state *svsp, int n)
fillw(user_attr | ' ',
(caddr_t)(svsp->Crtat + ((svsp->scrr_end - n + 1) * svsp->maxcol)),
n * svsp->maxcol);
-
-/*XXX*/ if (svsp->scroll_lock && svsp->openf && curproc)
- tsleep((caddr_t)&(svsp->scroll_lock), PUSER, "scrlck", 0);
}
/*---------------------------------------------------------------------------*
@@ -2063,9 +2060,6 @@ roll_down(struct video_state *svsp, int n)
fillw(user_attr | ' ',
(caddr_t)(svsp->Crtat + (svsp->scrr_beg * svsp->maxcol)),
n * svsp->maxcol);
-
-/*XXX*/ if (svsp->scroll_lock && svsp->openf && curproc)
- tsleep((caddr_t)&(svsp->scroll_lock), PUSER, "scrlck", 0);
}
/*---------------------------------------------------------------------------*