aboutsummaryrefslogtreecommitdiff
path: root/mubios/drivers
diff options
context:
space:
mode:
authorRichard Qin <richard.qin.x@gmail.com>2026-11-10 01:16:40 +0800
committerRichard Qin <richard.qin.x@gmail.com>2026-11-10 01:16:40 +0800
commit4a9624da0c7cf0c27a00e1ff497d13f2e4a0d03e (patch)
tree91b95e736fa08a071e7814872fc822c2d3fcd682 /mubios/drivers
parent9f45c30789b6133d4b5fb4ef07f0818a3ea4de48 (diff)
downloadrcc-project-4a9624da0c7cf0c27a00e1ff497d13f2e4a0d03e.tar.gz
rcc-project-4a9624da0c7cf0c27a00e1ff497d13f2e4a0d03e.tar.xz
[mubios] Implement serial input and BIOS console key handling
Implement UART receive, transmit timeouts, configuration and status reporting for INT 14h functions 00h-03h. Initialize the BDA serial timeout and expose the driver interfaces. Translate terminal characters and CSI/SS3 escape sequences into BIOS keyboard events for INT 16h. Add blocking reads, non-consuming status queries, enhanced key reads and keyboard buffer insertion.
Diffstat (limited to 'mubios/drivers')
-rw-r--r--mubios/drivers/ata.c3
-rw-r--r--mubios/drivers/ioapic.c2
-rw-r--r--mubios/drivers/kbd.c12
-rw-r--r--mubios/drivers/serial.c113
-rw-r--r--mubios/drivers/vga.c27
5 files changed, 134 insertions, 23 deletions
diff --git a/mubios/drivers/ata.c b/mubios/drivers/ata.c
index 86bab21..7d23a9c 100644
--- a/mubios/drivers/ata.c
+++ b/mubios/drivers/ata.c
@@ -96,8 +96,7 @@ ata_read_transfer28 (u32 lba, u16 *buffer, u16 count)
for (sector = 0; sector < count; ++sector)
{
status = ata_wait_not_busy ();
- if ((status & ATA_STATUS_ERR) != 0
- || (status & ATA_STATUS_DRQ) == 0)
+ if ((status & ATA_STATUS_ERR) != 0 || (status & ATA_STATUS_DRQ) == 0)
return 1;
for (index = 0; index < 256; ++index)
diff --git a/mubios/drivers/ioapic.c b/mubios/drivers/ioapic.c
index 7a0b6cb..552f497 100644
--- a/mubios/drivers/ioapic.c
+++ b/mubios/drivers/ioapic.c
@@ -84,7 +84,7 @@ ioapic_mask_all (void)
for (pin = 0; pin <= maximum_pin; ++pin)
{
ioapic_write ((u8)(IOAPIC_REDIRECTION_BASE + 2u * pin),
- IOAPIC_REDIRECTION_MASK);
+ IOAPIC_REDIRECTION_MASK);
ioapic_write ((u8)(IOAPIC_REDIRECTION_BASE + 2u * pin + 1u), 0);
}
}
diff --git a/mubios/drivers/kbd.c b/mubios/drivers/kbd.c
index 4de0a96..eb99e70 100644
--- a/mubios/drivers/kbd.c
+++ b/mubios/drivers/kbd.c
@@ -33,9 +33,9 @@
/*
* 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.
+ * 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
@@ -103,7 +103,8 @@ kbd_init (void)
/* 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. */
+ /* 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);
@@ -115,7 +116,8 @@ kbd_init (void)
config = io_in8 (KBD_DATA_PORT);
- config &= (u8)~(KBD_CONFIG_DISABLE_KBD_CLOCK | KBD_CONFIG_DISABLE_AUX_CLOCK);
+ 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)
diff --git a/mubios/drivers/serial.c b/mubios/drivers/serial.c
index 3da2093..c8b9adf 100644
--- a/mubios/drivers/serial.c
+++ b/mubios/drivers/serial.c
@@ -30,6 +30,7 @@
#define COM_LCR_OFFSET 0x03u
#define COM_MCR_OFFSET 0x04u
#define COM_LSR_OFFSET 0x05u
+#define COM_MSR_OFFSET 0x06u
#define COM_LCR_DLAB 0x80u
#define COM_LCR_8N1 0x03u
@@ -44,6 +45,12 @@
#define COM_MCR_OUT2 0x08u
#define COM_LSR_THRE 0x20u
+#define COM_LSR_IDLE 0x40u
+#define COM_LSR_DATA_READY 0x01u
+#define BIOS_SERIAL_TIMEOUT 0x80u
+
+#define PIT_COUNTER0 0x0040u
+#define PIT_COMMAND 0x0043u
static u16
com1_port (u16 offset)
@@ -51,6 +58,112 @@ com1_port (u16 offset)
return (u16)(COM1_BASE + offset);
}
+/* Latching channel 0 works while the protected-mode service has IRQs off. */
+u16
+serial_timer_counter (void)
+{
+ u16 counter;
+
+ io_out8 (PIT_COMMAND, 0x00u);
+ counter = io_in8 (PIT_COUNTER0);
+ counter |= (u16)((u16)io_in8 (PIT_COUNTER0) << 8);
+ return counter;
+}
+
+static int
+serial_wait (u16 base, u8 mask, u8 timeout, u8 *status)
+{
+ u16 previous;
+ u16 current;
+ u32 elapsed;
+ u32 duration;
+
+ previous = serial_timer_counter ();
+ elapsed = 0;
+ /* One BDA timeout unit is one 65536-clock BIOS timer tick. */
+ duration = (u32)timeout << 16;
+
+ for (;;)
+ {
+ *status = io_in8 ((u16)(base + COM_LSR_OFFSET));
+ if ((*status & mask) == mask)
+ return 1;
+
+ if (elapsed >= duration)
+ {
+ *status |= BIOS_SERIAL_TIMEOUT;
+ return 0;
+ }
+
+ current = serial_timer_counter ();
+ elapsed += (u16)(previous - current);
+ previous = current;
+ }
+}
+
+u16
+serial_status (u16 base)
+{
+ u8 line;
+ u8 modem;
+
+ line = io_in8 ((u16)(base + COM_LSR_OFFSET));
+ modem = io_in8 ((u16)(base + COM_MSR_OFFSET));
+ return (u16)(((u16)line << 8) | modem);
+}
+
+u16
+serial_configure (u16 base, u8 parameters)
+{
+ static const u16 divisors[]
+ = { 1047u, 768u, 384u, 192u, 96u, 48u, 24u, 12u };
+ u16 divisor;
+
+ /* INT 14h AL: bits 7:5 select baud; bits 4:0 are the UART format. */
+ divisor = divisors[parameters >> 5];
+ io_out8 ((u16)(base + COM_LCR_OFFSET), COM_LCR_DLAB);
+ io_out8 ((u16)(base + COM_DATA_OFFSET), (u8)divisor);
+ io_out8 ((u16)(base + COM_IER_OFFSET), (u8)(divisor >> 8));
+ io_out8 ((u16)(base + COM_LCR_OFFSET), parameters & 0x1Fu);
+ /* Do not reset the FIFO here: pending terminal input must survive. */
+ return serial_status (base);
+}
+
+u8
+serial_transmit (u16 base, u8 value, u8 timeout)
+{
+ u8 status;
+
+ if (serial_wait (base, COM_LSR_THRE | COM_LSR_IDLE, timeout, &status))
+ io_out8 ((u16)(base + COM_DATA_OFFSET), value);
+
+ return status;
+}
+
+u8
+serial_receive (u16 base, u8 *value, u8 timeout)
+{
+ u8 status;
+
+ if (serial_wait (base, COM_LSR_DATA_READY, timeout, &status))
+ *value = io_in8 ((u16)(base + COM_DATA_OFFSET));
+
+ return status;
+}
+
+int
+serial_try_receive (u16 base, u8 *value)
+{
+ u8 status;
+
+ status = io_in8 ((u16)(base + COM_LSR_OFFSET));
+ if ((status & COM_LSR_DATA_READY) == 0u)
+ return 0;
+
+ *value = io_in8 ((u16)(base + COM_DATA_OFFSET));
+ return 1;
+}
+
void
serial_init (void)
{
diff --git a/mubios/drivers/vga.c b/mubios/drivers/vga.c
index 57e1f8f..16f88e5 100644
--- a/mubios/drivers/vga.c
+++ b/mubios/drivers/vga.c
@@ -35,8 +35,7 @@
#define VGA_ATTR_INDEX_DATA 0x03C0u
static void
-vga_write_registers (u16 index_port, u16 data_port, const u8 *values,
- u8 count)
+vga_write_registers (u16 index_port, u16 data_port, const u8 *values, u8 count)
{
u8 index;
@@ -50,19 +49,17 @@ vga_write_registers (u16 index_port, u16 data_port, const u8 *values,
void
vga_text_mode_init (void)
{
- static const u8 sequencer[] = {0x00u, 0x00u, 0x03u, 0x00u, 0x02u};
- static const u8 crtc[] = {0x5Fu, 0x4Fu, 0x50u, 0x82u, 0x55u, 0x81u,
- 0xBFu, 0x1Fu, 0x00u, 0x4Fu, 0x0Du, 0x0Eu,
- 0x00u, 0x00u, 0x00u, 0x00u, 0x9Cu, 0x8Eu,
- 0x8Fu, 0x28u, 0x1Fu, 0x96u, 0xB9u, 0xA3u,
- 0xFFu};
- static const u8 graphics[] = {0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
- 0x10u, 0x0Fu, 0x00u, 0xFFu};
- static const u8 attributes[] = {0x00u, 0x01u, 0x02u, 0x03u, 0x04u,
- 0x05u, 0x06u, 0x07u, 0x08u, 0x09u,
- 0x0Au, 0x0Bu, 0x0Cu, 0x0Du, 0x0Eu,
- 0x0Fu, 0x0Cu, 0x00u, 0x0Fu, 0x08u,
- 0x00u};
+ static const u8 sequencer[] = { 0x00u, 0x00u, 0x03u, 0x00u, 0x02u };
+ static const u8 crtc[]
+ = { 0x5Fu, 0x4Fu, 0x50u, 0x82u, 0x55u, 0x81u, 0xBFu, 0x1Fu, 0x00u,
+ 0x4Fu, 0x0Du, 0x0Eu, 0x00u, 0x00u, 0x00u, 0x00u, 0x9Cu, 0x8Eu,
+ 0x8Fu, 0x28u, 0x1Fu, 0x96u, 0xB9u, 0xA3u, 0xFFu };
+ static const u8 graphics[]
+ = { 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x10u, 0x0Fu, 0x00u, 0xFFu };
+ static const u8 attributes[]
+ = { 0x00u, 0x01u, 0x02u, 0x03u, 0x04u, 0x05u, 0x06u,
+ 0x07u, 0x08u, 0x09u, 0x0Au, 0x0Bu, 0x0Cu, 0x0Du,
+ 0x0Eu, 0x0Fu, 0x0Cu, 0x00u, 0x0Fu, 0x08u, 0x00u };
volatile u16 *video;
volatile u8 *bda;
u16 cell;