this diff changes the way ps/2 and AT keyboards are handled in
attempt to gain support for some quirky ones.  this includes most
laptops that have internally connected ps/2 keyboards.

if you want your keyboard to continue working for the 4.1 release,
please test this change now and report back to me privately,
off-list, whether your keyboard continues to work or not.  include
relevant details like what kind of keyboard it is and a dmesg.


Index: dev/pckbc/pckbd.c
===================================================================
RCS file: /cvs/src/sys/dev/pckbc/pckbd.c,v
retrieving revision 1.8
diff -u -r1.8 pckbd.c
--- dev/pckbc/pckbd.c   29 Dec 2005 12:31:29 -0000      1.8
+++ dev/pckbc/pckbd.c   10 Jan 2007 15:58:01 -0000
@@ -192,54 +192,75 @@
        pckbc_tag_t kbctag;
        pckbc_slot_t kbcslot;
 {
-       u_char cmd[2];
-       int res;
+       /* default to have the 8042 translate the keyboard with table 3 */
+       int x = 3;
 
-       /*
-        * Some keyboard/8042 combinations do not seem to work if the keyboard
-        * is set to table 1; in fact, it would appear that some keyboards just
-        * ignore the command altogether.  So by default, we use the AT scan
-        * codes and have the 8042 translate them.  Unfortunately, this is
-        * known to not work on some PS/2 machines.  We try desperately to deal
-        * with this by checking the (lack of a) translate bit in the 8042 and
-        * attempting to set the keyboard to XT mode.  If this all fails, well,
-        * tough luck.
-        *
-        * XXX It would perhaps be a better choice to just use AT scan codes
-        * and not bother with this.
-        */
-       if (pckbc_xt_translation(kbctag, kbcslot, 1)) {
-               /* The 8042 is translating for us; use AT codes. */
+       if (!pckbc_xt_translation(kbctag, kbcslot, 1)) {
+#ifdef DEBUG
+               printf("pckbd: enabling of translation failed\n");
+#endif
+               /* just set the basic XT table and hope it works */
+               x = 1;
+       }
+
+       /* keep falling back until we hit a table that looks usable */
+       for (; x >= 1; x--) {
+               u_char cmd[2];
+#ifdef DEBUG
+               printf("pckbd: trying table %d\n", x);
+#endif
                cmd[0] = KBC_SETTABLE;
-               cmd[1] = 2;
-               res = pckbc_poll_cmd(kbctag, kbcslot, cmd, 2, 0, 0, 0);
-               if (res) {
+               cmd[1] = x;
+               if (pckbc_poll_cmd(kbctag, kbcslot, cmd, 2, 0, 0, 0)) {
                        u_char cmd[1];
 #ifdef DEBUG
-                       printf("pckbd: error setting scanset 2\n");
+                       printf("pckbd: table set of %d failed");
 #endif
-                       /*
-                        * XXX at least one keyboard is reported to lock up
-                        * if a "set table" is attempted, thus the "reset".
-                        * XXX ignore errors, scanset 2 should be
-                        * default anyway.
-                        */
                        cmd[0] = KBC_RESET;
                        (void)pckbc_poll_cmd(kbctag, kbcslot, cmd, 1, 1, 0, 1);
                        pckbc_flush(kbctag, kbcslot);
-                       res = 0;
+
+                       continue;
                }
-       } else {
-               /* Stupid 8042; set keyboard to XT codes. */
-               cmd[0] = KBC_SETTABLE;
-               cmd[1] = 1;
-               res = pckbc_poll_cmd(kbctag, kbcslot, cmd, 2, 0, 0, 0);
+
+               /* the 8042 took the table set request */
+
+               if (x == 3) {
+                       /* however, not all that say they can go into table 3
+                        * actually work, so ask what table it's in now */
+
+                       u_char cmd[1], resp[0];
+
+                       cmd[0] = KBC_SETTABLE;
+                       cmd[1] = 0;
+                       if (pckbc_poll_cmd(kbctag, kbcslot, cmd, 2, 1, resp, 
0)) {
+#ifdef DEBUG
+                               printf("pckbd: table 3 verification failed\n");
+#endif
+                               /* query failed, let's just step down to table
+                                * 2 to be safe */
+
+                               continue;
+                       } else if (resp[0] == 3) {
+#ifdef DEBUG
+                               printf("pckbd: settling on set 3\n");
+#endif
+                               return (0);
+                       }
+#ifdef DEBUG
+                       else
+                               printf("pckbd: set %x != 3, trying 2\n",
+                                       resp[0]);
+#endif
+               } else {
 #ifdef DEBUG
-               if (res)
-                       printf("pckbd: error setting scanset 1\n");
+                       printf("pckbd: settling on set %d\n", x);
 #endif
+                       return (0);
+               }
        }
-       return (res);
+
+       return (1);
 }
 
 static int

Reply via email to