From 4a9624da0c7cf0c27a00e1ff497d13f2e4a0d03e Mon Sep 17 00:00:00 2001 From: Richard Qin Date: Tue, 10 Nov 2026 01:16:40 +0800 Subject: [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. --- mubios/services/int14.c | 75 +++++++++++++++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 31 deletions(-) (limited to 'mubios/services/int14.c') diff --git a/mubios/services/int14.c b/mubios/services/int14.c index 86019b7..0cf25fb 100644 --- a/mubios/services/int14.c +++ b/mubios/services/int14.c @@ -7,55 +7,68 @@ */ #include "bios.h" -#include "io.h" #include "regs.h" -#define COM1_BASE 0x03F8u -#define COM_DATA 0x00u -#define COM_LSR 0x05u -#define COM_LSR_THRE 0x20u -#define COM_LSR_IDLE 0x40u - -static void -int14_putc (u8 value) -{ - while ((io_in8 ((u16)(COM1_BASE + COM_LSR)) & COM_LSR_THRE) == 0u) - { - } - - io_out8 ((u16)(COM1_BASE + COM_DATA), value); -} +#define BIOS_CF 0x0001u +#define BIOS_INVALID_FUNCTION 0x86u +#define BDA_COM_PORTS 0x0400u +#define BDA_COM_TIMEOUTS 0x047Cu +#define BIOS_COM_PORT_COUNT 4u void int14_service (struct bios_regs *regs) { u8 function; u8 status; + u8 value; + u8 timeout; + u16 port; + u16 base; + u16 result; + volatile u16 *ports; + volatile u8 *timeouts; function = (u8)(regs->eax >> 8); + port = (u16)regs->edx; + ports = (volatile u16 *)BDA_COM_PORTS; + timeouts = (volatile u8 *)BDA_COM_TIMEOUTS; - if (function == 0x00u) + /* BIOS numbers COM ports through DX and advertises their bases in BDA. */ + if (function > 0x03u || port >= BIOS_COM_PORT_COUNT || ports[port] == 0u) { - serial_init (); - regs->eax &= 0xFFFF0000u; + regs->eax + = (regs->eax & 0xFFFF00FFu) | ((u32)BIOS_INVALID_FUNCTION << 8); + regs->flags |= BIOS_CF; return; } - if (function == 0x01u) - { - int14_putc ((u8)regs->eax); - status = (u8)(io_in8 ((u16)(COM1_BASE + COM_LSR)) - | COM_LSR_THRE | COM_LSR_IDLE); - regs->eax = (regs->eax & 0xFFFF00FFu) | ((u32)status << 8); - return; - } + base = ports[port]; + timeout = timeouts[port]; - if (function == 0x03u) + switch (function) { - status = io_in8 ((u16)(COM1_BASE + COM_LSR)); + case 0x00u: + result = serial_configure (base, (u8)regs->eax); + regs->eax = (regs->eax & 0xFFFF0000u) | result; + break; + + case 0x01u: + status = serial_transmit (base, (u8)regs->eax, timeout); regs->eax = (regs->eax & 0xFFFF00FFu) | ((u32)status << 8); - return; + break; + + case 0x02u: + value = (u8)regs->eax; + status = serial_receive (base, &value, timeout); + regs->eax = (regs->eax & 0xFFFF0000u) | ((u32)status << 8) | value; + break; + + case 0x03u: + result = serial_status (base); + regs->eax = (regs->eax & 0xFFFF0000u) | result; + break; } - regs->eax = 0x0100u; + /* As in SeaBIOS, timeouts use AH bit 7; CF denotes an invalid call. */ + regs->flags &= (u16)~BIOS_CF; } -- cgit v1.2.3