Rework disabling of ps2 port irqs.

Disable the ps2 port irqs in software instead of hardware.  This
prevents a race where an irq could get queued and later called when
not desired.
diff --git a/src/biosvar.h b/src/biosvar.h
index b6e061b..2e43f8b 100644
--- a/src/biosvar.h
+++ b/src/biosvar.h
@@ -97,7 +97,7 @@
     u8 floppy_media_state[4];
     u8 floppy_track[2];
     u8 kbd_flag2;
-    u8 kbd_led;
+    u8 kbd_flag3;
     struct segoff_s user_wait_complete_flag;
     u32 user_wait_timeout;
     // 40:A0
@@ -123,6 +123,33 @@
 #define FMS_DOUBLE_STEPPING         (1<<5)
 #define FMS_DATA_RATE_MASK          (0xc0)
 
+// Bit definitions for kbd_flag[0123]
+#define KF0_RSHIFT       (1<<0)
+#define KF0_LSHIFT       (1<<1)
+#define KF0_CTRLACTIVE   (1<<2)
+#define KF0_ALTACTIVE    (1<<3)
+#define KF0_SCROLLACTIVE (1<<4)
+#define KF0_NUMACTIVE    (1<<5)
+#define KF0_CAPSACTIVE   (1<<6)
+
+#define KF1_LCTRL        (1<<0)
+#define KF1_LALT         (1<<1)
+#define KF1_PAUSEACTIVE  (1<<3)
+#define KF1_SCROLL       (1<<4)
+#define KF1_NUM          (1<<5)
+#define KF1_CAPS         (1<<6)
+
+#define KF2_LAST_E1    (1<<0)
+#define KF2_LAST_E0    (1<<1)
+#define KF2_RCTRL      (1<<2)
+#define KF2_RALT       (1<<3)
+#define KF2_101KBD     (1<<4)
+
+#define KF3_SCROLL_LED  (1<<0)
+#define KF3_NUM_LED     (1<<1)
+#define KF3_CAPS_LED    (1<<2)
+#define KF3_CMD_PENDING (1<<6)
+
 // Accessor functions
 #define GET_BDA(var) \
     GET_FARVAR(SEG_BDA, ((struct bios_data_area_s *)0)->var)
@@ -205,7 +232,6 @@
     u8 other2[0xC4];
 
     // 0x121 - Begin custom storage.
-    u8 ps2ctr;
     int RTCusers;
 
     // El Torito Emulation data
diff --git a/src/kbd.c b/src/kbd.c
index 6f3ae15..44dce57 100644
--- a/src/kbd.c
+++ b/src/kbd.c
@@ -11,28 +11,6 @@
 #include "bregs.h" // struct bregs
 #include "ps2port.h" // kbd_command
 
-// Bit definitions for BDA kbd_flag[012]
-#define KF0_RSHIFT       (1<<0)
-#define KF0_LSHIFT       (1<<1)
-#define KF0_CTRLACTIVE   (1<<2)
-#define KF0_ALTACTIVE    (1<<3)
-#define KF0_SCROLLACTIVE (1<<4)
-#define KF0_NUMACTIVE    (1<<5)
-#define KF0_CAPSACTIVE   (1<<6)
-
-#define KF1_LCTRL        (1<<0)
-#define KF1_LALT         (1<<1)
-#define KF1_PAUSEACTIVE  (1<<3)
-#define KF1_SCROLL       (1<<4)
-#define KF1_NUM          (1<<5)
-#define KF1_CAPS         (1<<6)
-
-#define KF2_LAST_E1    (1<<0)
-#define KF2_LAST_E0    (1<<1)
-#define KF2_RCTRL      (1<<2)
-#define KF2_RALT       (1<<3)
-#define KF2_101KBD     (1<<4)
-
 void
 kbd_setup(void)
 {
@@ -223,7 +201,7 @@
 set_leds(void)
 {
     u8 shift_flags = (GET_BDA(kbd_flag0) >> 4) & 0x07;
-    u8 kbd_led = GET_BDA(kbd_led);
+    u8 kbd_led = GET_BDA(kbd_flag3);
     u8 led_flags = kbd_led & 0x07;
     if (shift_flags == led_flags)
         return;
@@ -233,7 +211,7 @@
         // Error
         return;
     kbd_led = (kbd_led & ~0x07) | shift_flags;
-    SET_BDA(kbd_led, kbd_led);
+    SET_BDA(kbd_flag3, kbd_led);
 }
 
 // INT 16h Keyboard Service Entry Point
diff --git a/src/mouse.c b/src/mouse.c
index 52e225c..888d32d 100644
--- a/src/mouse.c
+++ b/src/mouse.c
@@ -29,13 +29,8 @@
 #define RET_ENOHANDLER   0x05
 
 static int
-disable_mouse(u16 ebda_seg)
+disable_mouse(void)
 {
-    u8 ps2ctr = GET_EBDA2(ebda_seg, ps2ctr);
-    ps2ctr |= I8042_CTR_AUXDIS;
-    ps2ctr &= ~I8042_CTR_AUXINT;
-    SET_EBDA2(ebda_seg, ps2ctr, ps2ctr);
-
     return aux_command(PSMOUSE_CMD_DISABLE, NULL);
 }
 
@@ -43,8 +38,7 @@
 static void
 mouse_15c20000(struct bregs *regs)
 {
-    u16 ebda_seg = get_ebda_seg();
-    int ret = disable_mouse(ebda_seg);
+    int ret = disable_mouse();
     if (ret)
         set_code_invalid(regs, RET_ENEEDRESEND);
     else
@@ -55,18 +49,12 @@
 static void
 mouse_15c20001(struct bregs *regs)
 {
-    u16 ebda_seg = get_ebda_seg();
-    u8 mouse_flags_2 = GET_EBDA2(ebda_seg, mouse_flag2);
+    u8 mouse_flags_2 = GET_EBDA(mouse_flag2);
     if ((mouse_flags_2 & 0x80) == 0) {
         set_code_invalid(regs, RET_ENOHANDLER);
         return;
     }
 
-    u8 ps2ctr = GET_EBDA2(ebda_seg, ps2ctr);
-    ps2ctr &= ~I8042_CTR_AUXDIS;
-    ps2ctr |= I8042_CTR_AUXINT;
-    SET_EBDA2(ebda_seg, ps2ctr, ps2ctr);
-
     int ret = aux_command(PSMOUSE_CMD_ENABLE, NULL);
     if (ret)
         set_code_invalid(regs, RET_ENEEDRESEND);
@@ -241,7 +229,7 @@
         /* remove handler */
         if ((mouse_flags_2 & 0x80) != 0) {
             mouse_flags_2 &= ~0x80;
-            disable_mouse(ebda_seg);
+            disable_mouse();
         }
     } else {
         /* install handler */
diff --git a/src/ps2port.c b/src/ps2port.c
index fb9d24a..b52f994 100644
--- a/src/ps2port.c
+++ b/src/ps2port.c
@@ -151,6 +151,18 @@
         process_key(data);
 }
 
+static void
+process_ps2bytes(void)
+{
+    for (;;) {
+        u8 status = inb(PORT_PS2_STATUS);
+        if (!(status & I8042_STR_OBF))
+            return;
+        u8 data = inb(PORT_PS2_DATA);
+        process_ps2byte(status, data);
+    }
+}
+
 static int
 ps2_recvbyte(int aux, int needack, int timeout)
 {
@@ -209,22 +221,13 @@
 static int
 ps2_command(int aux, int command, u8 *param)
 {
-    int ret2;
+    int ret;
     int receive = (command >> 8) & 0xf;
     int send = (command >> 12) & 0xf;
 
-    // Disable interrupts and keyboard/mouse.
-    u8 ps2ctr = GET_EBDA(ps2ctr);
-    u8 newctr = ps2ctr;
-    if (aux)
-        newctr |= I8042_CTR_KBDDIS;
-    else
-        newctr |= I8042_CTR_AUXDIS;
-    newctr &= ~(I8042_CTR_KBDINT|I8042_CTR_AUXINT);
-    dprintf(6, "i8042 ctr old=%x new=%x\n", ps2ctr, newctr);
-    int ret = i8042_command(I8042_CMD_CTL_WCTR, &newctr);
-    if (ret)
-        return ret;
+    // Disable processing of interrupts.
+    u8 kbdflag = GET_BDA(kbd_flag3);
+    SET_BDA(kbd_flag3, kbdflag | KF3_CMD_PENDING);
 
     if (command == ATKBD_CMD_RESET_BAT) {
         // Reset is special wrt timeouts.
@@ -270,10 +273,10 @@
     ret = 0;
 
 fail:
-    // Restore interrupts and keyboard/mouse.
-    ret2 = i8042_command(I8042_CMD_CTL_WCTR, &ps2ctr);
-    if (ret2)
-        return ret2;
+    // Restore processing of interrupts.
+    if (!(kbdflag & KF3_CMD_PENDING))
+        process_ps2bytes();
+    SET_BDA(kbd_flag3, kbdflag);
 
     return ret;
 }
@@ -306,14 +309,10 @@
 static void
 process_ps2irq(void)
 {
-    u8 status = inb(PORT_PS2_STATUS);
-    if (!(status & I8042_STR_OBF)) {
-        dprintf(1, "ps2 irq but no data.\n");
+    if (GET_BDA(kbd_flag3) & KF3_CMD_PENDING)
+        // PS/2 command in progress - it will handle this event.
         return;
-    }
-    u8 data = inb(PORT_PS2_DATA);
-
-    process_ps2byte(status, data);
+    process_ps2bytes();
 }
 
 // INT74h : PS/2 mouse hardware interrupt
@@ -402,8 +401,12 @@
     if (ret)
         return;
 
-    // Keyboard Mode: scan code convert, disable mouse, enable IRQ 1
-    SET_EBDA(ps2ctr, I8042_CTR_AUXDIS | I8042_CTR_XLATE | I8042_CTR_KBDINT);
+    // Mode: scan code convert, enable IRQ 1, enable IRQ 12
+    param[0] = I8042_CTR_XLATE | I8042_CTR_KBDINT | I8042_CTR_AUXINT;
+    ret = i8042_command(I8042_CMD_CTL_WCTR, param);
+    if (ret)
+        return;
+    CLEARBITS_BDA(kbd_flag3, KF3_CMD_PENDING);
 
     /* Enable keyboard */
     ret = kbd_command(ATKBD_CMD_ENABLE, NULL);
@@ -420,6 +423,8 @@
         return;
     dprintf(3, "init ps2port\n");
 
+    // Setup irqs, but disable them until init complete.
+    SETBITS_BDA(kbd_flag3, KF3_CMD_PENDING);
     enable_hwirq(1, entry_09);
     enable_hwirq(12, entry_74);