This fixes a bug in pcvt wrt LED updating that could hang the keyboard.
Apply by doing:
cd /usr/src/sys/arch/i386/isa/pcvt
patch -p0 < pcvt.patch
Then rebuild the kernel you use.
--- pcvt_conf.h.DIST Mon Mar 9 16:26:04 1998
+++ pcvt_conf.h Wed Jul 1 11:34:09 1998
@@ -301,10 +301,10 @@
/* it is unlikely that anybody wants to change anything below */
#if !defined PCVT_NO_LED_UPDATE /* ---------- DEFAULT: OFF ------------ */
-# define PCVT_NO_LED_UPDATE 0 /* On some (Notebook?) keyboards it is */
+# define PCVT_NO_LED_UPDATE 0 /* On some keyboard controllers it is */
#elif PCVT_NO_LED_UPDATE != 0 /* not possible to update the LED's */
# undef PCVT_NO_LED_UPDATE /* without hanging the keyboard after- */
-# define PCVT_NO_LED_UPDATE 1 /* wards. If you experience Problems */
+# define PCVT_NO_LED_UPDATE 1 /* wards. If you experience problems */
#endif /* like this, try to enable this option */
/*
* This code from Lon Willett enclosed in #if PCVT_UPDLED_LOSES_INTR is
- * abled because it crashes FreeBSD 1.1.5.1 at boot time.
+ * disabled because it crashes FreeBSD 1.1.5.1 at boot time.
* The cause is obviously that the timeout queue is not yet initialized
* timeout is called from here the first time.
* Anyway it is a pointer in the right direction so it is included for
@@ -224,24 +228,60 @@
if (new_ledstate != ledstate)
{
- if(kbd_cmd(KEYB_C_LEDS) != 0)
+ ledstate = LEDSTATE_UPDATE_PENDING;
+
+ if (kbd_cmd(KEYB_C_LEDS) != 0)
{
printf("Keyboard LED command timeout\n");
+ splx(opri);
return;
}
- if(kbd_cmd(new_ledstate) != 0) {
+ /*
+ * For some keyboards or keyboard controllers, it is an
+ * error to issue a command without waiting long enough
+ * for an ACK for the previous command. The keyboard
+ * gets confused, and responds with KEYB_R_RESEND, but
+ * we ignore that. Wait for the ACK here. The busy
+ * waiting doesn't matter much, since we lose anyway by
+ * busy waiting to send the command.
+ *
+ * XXX actually wait for any response, since we can't
+ * handle normal scancodes here.
+ *
+ * XXX all this should be interrupt driven. Issue only
+ * one command at a time wait for a ACK before proceeding.
+ * Retry after a timeout or on receipt of a KEYB_R_RESEND.
+ * KEYB_R_RESENDs seem to be guaranteed by working
+ * keyboard controllers with broken (or disconnected)
+ * keyboards. There is another code for keyboard
+ * reconnects. The keyboard hardware is very simple and
+ * well designed :-).
+ */
+ response1 = kbd_response();
+
+ if (kbd_cmd(new_ledstate) != 0) {
printf("Keyboard LED data timeout\n");
+ splx(opri);
return;
}
+ response2 = kbd_response();