aboutsummaryrefslogtreecommitdiff
path: root/mubios/drivers/kbd.c
diff options
context:
space:
mode:
authorRichard Qin <richard.qin.x@gmail.com>2026-11-09 23:42:19 +0800
committerRichard Qin <richard.qin.x@gmail.com>2026-11-09 23:42:19 +0800
commit2bc8a824fd424aa3e21bc394fd0be3191b830888 (patch)
tree4b6fcfc27e6caa1d80c4f35dbb410620815ae262 /mubios/drivers/kbd.c
parent06cb46aa0236352554f23697e17bed378083be1a (diff)
downloadrcc-project-2bc8a824fd424aa3e21bc394fd0be3191b830888.tar.gz
rcc-project-2bc8a824fd424aa3e21bc394fd0be3191b830888.tar.xz
[mubios] Initialize the 8042 keyboard controller
POST only unmasked IRQ1 in the PIC and never configured the 8042 itself, so the keyboard stayed in its post-reset disabled state: the clock was inhibited and no scan code ever reached the output buffer. IRQ1 never fired, the BDA keyboard buffer stayed empty, and GRUB polling INT 16h AH=01h never saw a key. Add kbd_init() to disable both ports, drain the output buffer, clear the clock inhibit bits in the command byte, enable the keyboard and auxiliary IRQs and select set 1 translation, then enable scanning with 0xF4. The IRQ1 handler now checks the status register for a pending output byte before reading the data port and drops auxiliary port bytes. The set 2 break prefix tracking is gone because translation is enabled.
Diffstat (limited to 'mubios/drivers/kbd.c')
-rw-r--r--mubios/drivers/kbd.c133
1 files changed, 133 insertions, 0 deletions
diff --git a/mubios/drivers/kbd.c b/mubios/drivers/kbd.c
new file mode 100644
index 0000000..4de0a96
--- /dev/null
+++ b/mubios/drivers/kbd.c
@@ -0,0 +1,133 @@
+/*
+ RCC-Project
+
+ Copyright (C) 2026 Richard Qin
+
+ This file is part of RCC-Project.
+
+ RCC-Project is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your option)
+ any later version.
+
+ RCC-Project is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+ */
+
+#include "bios.h"
+#include "io.h"
+
+#define KBD_STATUS_PORT 0x0064u
+#define KBD_DATA_PORT 0x0060u
+
+#define KBD_STATUS_OBF 0x01u
+#define KBD_STATUS_IBF 0x02u
+#define KBD_STATUS_AUX 0x20u
+
+#define KBD_CMD_READ_CONFIG 0x20u
+#define KBD_CMD_WRITE_CONFIG 0x60u
+#define KBD_CMD_DISABLE_KBD 0xADu
+#define KBD_CMD_ENABLE_KBD 0xAEu
+
+/*
+ * 8042 command byte bits.
+ * Bit 0 enables the keyboard IRQ, bit 1 the auxiliary port IRQ, bit 4 and bit 5
+ * hold the keyboard and auxiliary clock, and bit 6 selects set 1 scan codes on
+ * the keyboard interface.
+ */
+#define KBD_CONFIG_IRQ1 0x01u
+#define KBD_CONFIG_IRQ12 0x02u
+#define KBD_CONFIG_DISABLE_KBD_CLOCK 0x10u
+#define KBD_CONFIG_DISABLE_AUX_CLOCK 0x20u
+#define KBD_CONFIG_TRANSLATE 0x40u
+
+#define KBD_DEVICE_ENABLE_SCAN 0xF4u
+
+#define KBD_WAIT_LIMIT 0x10000u
+
+static int
+wait_input_clear (void)
+{
+ u32 count;
+
+ for (count = 0; count < KBD_WAIT_LIMIT; count++)
+ {
+ if ((io_in8 (KBD_STATUS_PORT) & KBD_STATUS_IBF) == 0u)
+ return 0;
+ }
+
+ return -1;
+}
+
+static int
+wait_output_full (void)
+{
+ u32 count;
+
+ for (count = 0; count < KBD_WAIT_LIMIT; count++)
+ {
+ if ((io_in8 (KBD_STATUS_PORT) & KBD_STATUS_OBF) != 0u)
+ return 0;
+ }
+
+ return -1;
+}
+
+static int
+kbd_write_command (u8 command)
+{
+ if (wait_input_clear () != 0)
+ return -1;
+
+ io_out8 (KBD_STATUS_PORT, command);
+ return 0;
+}
+
+static int
+kbd_write_data (u8 value)
+{
+ if (wait_input_clear () != 0)
+ return -1;
+
+ io_out8 (KBD_DATA_PORT, value);
+ return 0;
+}
+
+void
+kbd_init (void)
+{
+ u8 config;
+
+ /* Disable both ports before the controller is reconfigured. */
+ kbd_write_command (KBD_CMD_DISABLE_KBD);
+
+ /* Drain the self-test and any pending scan code left in the output buffer. */
+ while ((io_in8 (KBD_STATUS_PORT) & KBD_STATUS_OBF) != 0u)
+ (void)io_in8 (KBD_DATA_PORT);
+
+ if (kbd_write_command (KBD_CMD_READ_CONFIG) != 0)
+ return;
+
+ if (wait_output_full () != 0)
+ return;
+
+ config = io_in8 (KBD_DATA_PORT);
+
+ config &= (u8)~(KBD_CONFIG_DISABLE_KBD_CLOCK | KBD_CONFIG_DISABLE_AUX_CLOCK);
+ config |= KBD_CONFIG_IRQ1 | KBD_CONFIG_IRQ12 | KBD_CONFIG_TRANSLATE;
+
+ if (kbd_write_command (KBD_CMD_WRITE_CONFIG) != 0)
+ return;
+
+ kbd_write_data (config);
+
+ kbd_write_command (KBD_CMD_ENABLE_KBD);
+
+ /* Ask the keyboard to start scanning and consume its acknowledge byte. */
+ kbd_write_data (KBD_DEVICE_ENABLE_SCAN);
+
+ if (wait_output_full () == 0)
+ (void)io_in8 (KBD_DATA_PORT);
+}