diff options
| author | Richard Qin <richard.qin.x@gmail.com> | 2026-11-09 23:42:19 +0800 |
|---|---|---|
| committer | Richard Qin <richard.qin.x@gmail.com> | 2026-11-09 23:42:19 +0800 |
| commit | 2bc8a824fd424aa3e21bc394fd0be3191b830888 (patch) | |
| tree | 4b6fcfc27e6caa1d80c4f35dbb410620815ae262 /mubios/drivers | |
| parent | 06cb46aa0236352554f23697e17bed378083be1a (diff) | |
| download | rcc-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')
| -rw-r--r-- | mubios/drivers/kbd.c | 133 |
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); +} |
