diff options
Diffstat (limited to 'mubios/services')
| -rw-r--r-- | mubios/services/int16.c | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/mubios/services/int16.c b/mubios/services/int16.c new file mode 100644 index 0000000..7acccfb --- /dev/null +++ b/mubios/services/int16.c @@ -0,0 +1,143 @@ +/* + 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 "regs.h" + +#define BIOS_ZF 0x0040u +#define BDA_KBD_HEAD 0x041Au +#define BDA_KBD_TAIL 0x041Cu +#define BDA_KBD_BUFFER 0x041Eu +#define BDA_KBD_BUFFER_END 0x043Eu + +static u8 +scancode_to_ascii (u8 scancode) +{ + switch (scancode) + { + case 0x1Eu: + return 'a'; + case 0x30u: + return 'b'; + case 0x2Eu: + return 'c'; + case 0x20u: + return 'd'; + case 0x12u: + return 'e'; + case 0x21u: + return 'f'; + case 0x22u: + return 'g'; + case 0x23u: + return 'h'; + case 0x17u: + return 'i'; + case 0x24u: + return 'j'; + case 0x25u: + return 'k'; + case 0x26u: + return 'l'; + case 0x32u: + return 'm'; + case 0x31u: + return 'n'; + case 0x18u: + return 'o'; + case 0x19u: + return 'p'; + case 0x10u: + return 'q'; + case 0x13u: + return 'r'; + case 0x1Fu: + return 's'; + case 0x14u: + return 't'; + case 0x16u: + return 'u'; + case 0x2Fu: + return 'v'; + case 0x11u: + return 'w'; + case 0x2Du: + return 'x'; + case 0x15u: + return 'y'; + case 0x2Cu: + return 'z'; + case 0x39u: + return ' '; + case 0x1Cu: + return '\r'; + default: + return 0; + } +} + +void +int16_service (struct bios_regs *regs) +{ + volatile u16 *head; + volatile u16 *tail; + volatile u16 *buffer; + u8 function; + u16 position; + u16 value; + u8 scancode; + u8 ascii; + + function = (u8)(regs->eax >> 8); + + if (function != 0x00u && function != 0x01u) + { + regs->eax = 0; + regs->flags |= BIOS_ZF; + return; + } + + head = (volatile u16 *)BDA_KBD_HEAD; + tail = (volatile u16 *)BDA_KBD_TAIL; + buffer = (volatile u16 *)BDA_KBD_BUFFER; + + if (*head == *tail) + { + regs->eax = 0; + regs->flags |= BIOS_ZF; + return; + } + + position = *head; + value = buffer[(position - BDA_KBD_BUFFER) >> 1]; + scancode = (u8)(value >> 8); + ascii = scancode_to_ascii (scancode); + + regs->eax = ((u32)scancode << 8) | ascii; + regs->flags &= (u16)~BIOS_ZF; + + if (function == 0x00u) + { + position += 2; + + if (position >= BDA_KBD_BUFFER_END) + position = BDA_KBD_BUFFER; + + *head = position; + } +} |
