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 */

#if !defined PCVT_PORTIO_DELAY  /* ---------- DEFAULT: ON ------------- */
--- pcvt_kbd.c.DIST     Mon Feb 23 14:28:32 1998
+++ pcvt_kbd.c  Wed Jul  1 11:34:09 1998
@@ -78,6 +78,8 @@

#include "pcvt_hdr.h"          /* global include */

+#define LEDSTATE_UPDATE_PENDING (1 << 3)
+
static void fkey1(void), fkey2(void),  fkey3(void),  fkey4(void);
static void fkey5(void), fkey6(void),  fkey7(void),  fkey8(void);
static void fkey9(void), fkey10(void), fkey11(void), fkey12(void);
@@ -106,7 +108,9 @@
static int     setkeydef ( struct kbd_ovlkey *data );
static u_char *        xlatkey2ascii( U_short key );

-static int     ledstate  = 0;  /* keyboard led's */
+#if !PCVT_NO_LED_UPDATE
+static int     ledstate  = LEDSTATE_UPDATE_PENDING;    /* keyboard led's */
+#endif
static int     tpmrate   = KBD_TPD500|KBD_TPM100;
static u_char  altkpflag = 0;
static u_short altkpval  = 0;
@@ -165,7 +169,7 @@

/*
 * 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 @@

       /* Don't update LED's unless necessary. */

-       int new_ledstate = ((vsp->scroll_lock) |
-                           (vsp->num_lock * 2) |
-                           (vsp->caps_lock * 4));
+       int opri, new_ledstate, response1, response2;
+
+       opri = spltty();
+       new_ledstate = ((vsp->scroll_lock) |
+                       (vsp->num_lock * 2) |
+                       (vsp->caps_lock * 4));

       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();

-               ledstate = new_ledstate;
+               if (response1 == KEYB_R_ACK && response2 == KEYB_R_ACK)
+                       ledstate = new_ledstate;
+               else
+                       printf(
+                       "Keyboard LED command not ACKed (responses %#x %#x)\n",
+                               response1, response2);

#if PCVT_UPDLED_LOSES_INTR
               if (lost_intr_timeout_queued)
@@ -252,6 +292,7 @@
#endif /* PCVT_UPDLED_LOSES_INTR */

       }
+       splx(opri);
#endif /* !PCVT_NO_LED_UPDATE */
}

@@ -432,7 +473,6 @@
               printf("pcvt: doreset() - timeout for keyboard reset command\n");

       /* Wait for the first response to reset and handle retries */
-
       while((response = kbd_response()) != KEYB_R_ACK)
       {
               if(response < 0)
@@ -533,12 +573,8 @@
r_entry:
               if((response = kbd_response()) == KEYB_R_MF2ID1)
               {
-                       if((response = kbd_response()) == KEYB_R_MF2ID2)
-                       {
-                               keyboard_type = KB_MFII;
-                       }
-                       else if(response == KEYB_R_RESEND)
-                       {
+                       switch ((response = kbd_response())) {
+                       case KEYB_R_RESEND:
                               /*
                                *  Let's give other priority levels
                                *  a chance instead of blocking at
@@ -546,24 +582,17 @@
                                */
                               splx(opri);
                               goto query_kbd_id;
-                       }
-                       else if(response == KEYB_R_MF2ID2HP)
-                       {
+
+                       case KEYB_R_MF2ID2:
+                       case KEYB_R_MF2ID2HP:
+                       case KEYB_R_MF2ID2TP:
+                       case KEYB_R_MF2ID2TP2:
                               keyboard_type = KB_MFII;
-                       }
-                       else if(response == KEYB_R_MF2ID2TP)
-                       {
-                               keyboard_type = KB_MFII;
-                       }
-                       else if(response == KEYB_R_MF2ID2TP2)
-                       {
-                               keyboard_type = KB_MFII;
-                       }
-                       else
-                       {
-                               printf("\npcvt: doreset() - kbdid, response 2 = [%d]\n",
-                                      response);
+                               break;
+                       default:
+                               printf("\npcvt: doreset() - kbdid, response 2 = [%d]\n", response);
                               keyboard_type = KB_UNKNOWN;
+                               break;
                       }
               }
               else if(response == KEYB_R_ACK)