aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Qin <richard.qin.x@gmail.com>2026-11-09 03:22:35 +0800
committerRichard Qin <richard.qin.x@gmail.com>2026-11-09 03:22:35 +0800
commit06cb46aa0236352554f23697e17bed378083be1a (patch)
tree099e92dce130d8f3b2bdbe9c88ddc3949babe94c
parenta54a4236a27e8319da421010fe0c3c5d80edca45 (diff)
downloadrcc-project-06cb46aa0236352554f23697e17bed378083be1a.tar.gz
rcc-project-06cb46aa0236352554f23697e17bed378083be1a.tar.xz
[mubios] Initialize VGA mode and serial BIOS services
-rw-r--r--mubios/arch/interrupt.S1
-rw-r--r--mubios/core/bda.c10
-rw-r--r--mubios/core/interrupt.c4
-rw-r--r--mubios/core/post.c1
-rw-r--r--mubios/drivers/vga.c112
-rw-r--r--mubios/include/bios.h2
-rw-r--r--mubios/linker.ld2
-rw-r--r--mubios/services/int10.c14
-rw-r--r--mubios/services/int14.c61
9 files changed, 205 insertions, 2 deletions
diff --git a/mubios/arch/interrupt.S b/mubios/arch/interrupt.S
index 021a83f..528b130 100644
--- a/mubios/arch/interrupt.S
+++ b/mubios/arch/interrupt.S
@@ -86,6 +86,7 @@ int1a_return:
.endm
BIOS_SERVICE_ENTRY int10_entry, 0x10
+ BIOS_SERVICE_ENTRY int14_entry, 0x14
BIOS_SERVICE_ENTRY int13_entry, 0x13
BIOS_SERVICE_ENTRY int15_entry, 0x15
BIOS_SERVICE_ENTRY int16_entry, 0x16
diff --git a/mubios/core/bda.c b/mubios/core/bda.c
index 4de2243..5aad85c 100644
--- a/mubios/core/bda.c
+++ b/mubios/core/bda.c
@@ -23,6 +23,9 @@
extern u8 __ebda_start[];
+#define BDA_COM1_OFFSET 0x0000u
+#define BDA_LPT1_OFFSET 0x0008u
+
static void
store_u16 (volatile u8 *address, u16 value)
{
@@ -41,7 +44,10 @@ bda_init (void)
store_u16 (bda + BDA_EBDA_SEGMENT_OFFSET, (u16)(ebda_base >> 4));
- store_u16 (bda + BDA_EQUIPMENT_OFFSET, (u16)(ebda_base >> 4));
+ store_u16 (bda + BDA_EQUIPMENT_OFFSET, 0x4227u);
+
+ store_u16 (bda + BDA_COM1_OFFSET, 0x03F8u);
+ store_u16 (bda + BDA_LPT1_OFFSET, 0x0378u);
store_u16 (bda + BDA_CONVENTIONAL_MEMORY_OFFSET, (u16)(ebda_base >> 10));
@@ -62,6 +68,7 @@ extern void irq7_entry (void);
extern void int1a_entry (void);
extern void int10_entry (void);
+extern void int14_entry (void);
extern void int13_entry (void);
extern void int15_entry (void);
extern void int16_entry (void);
@@ -89,6 +96,7 @@ ivt_init (void)
install_ivt_entry (0x0Fu, irq7_entry);
install_ivt_entry (0x1Au, int1a_entry);
install_ivt_entry (0x10u, int10_entry);
+ install_ivt_entry (0x14u, int14_entry);
install_ivt_entry (0x13u, int13_entry);
install_ivt_entry (0x15u, int15_entry);
install_ivt_entry (0x16u, int16_entry);
diff --git a/mubios/core/interrupt.c b/mubios/core/interrupt.c
index bf2ebc3..e038fae 100644
--- a/mubios/core/interrupt.c
+++ b/mubios/core/interrupt.c
@@ -31,6 +31,10 @@ bios_service_dispatch (u8 vector, struct bios_regs *regs)
int10_service (regs);
break;
+ case 0x14u:
+ int14_service (regs);
+ break;
+
case 0x13u:
int13_service (regs);
break;
diff --git a/mubios/core/post.c b/mubios/core/post.c
index 2af797b..7c6769f 100644
--- a/mubios/core/post.c
+++ b/mubios/core/post.c
@@ -29,6 +29,7 @@ post_main (void)
memory_init ();
bda_init ();
+ vga_text_mode_init ();
ivt_init ();
diff --git a/mubios/drivers/vga.c b/mubios/drivers/vga.c
new file mode 100644
index 0000000..57e1f8f
--- /dev/null
+++ b/mubios/drivers/vga.c
@@ -0,0 +1,112 @@
+/*
+ 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.
+ */
+
+#include "bios.h"
+#include "io.h"
+
+#define VGA_TEXT_BASE 0x000B8000u
+#define VGA_TEXT_CELLS 2000u
+
+#define BDA_VIDEO_MODE 0x0049u
+#define BDA_VIDEO_COLUMNS 0x004Au
+#define BDA_VIDEO_PAGE_SIZE 0x004Cu
+#define BDA_VIDEO_PAGE 0x0062u
+#define BDA_CURSOR_BASE 0x0450u
+#define BDA_CURSOR_SHAPE 0x0460u
+
+#define VGA_MISC_OUTPUT_WRITE 0x03C2u
+#define VGA_SEQ_INDEX 0x03C4u
+#define VGA_SEQ_DATA 0x03C5u
+#define VGA_CRTC_INDEX 0x03D4u
+#define VGA_CRTC_DATA 0x03D5u
+#define VGA_GC_INDEX 0x03CEu
+#define VGA_GC_DATA 0x03CFu
+#define VGA_INPUT_STATUS 0x03DAu
+#define VGA_ATTR_INDEX_DATA 0x03C0u
+
+static void
+vga_write_registers (u16 index_port, u16 data_port, const u8 *values,
+ u8 count)
+{
+ u8 index;
+
+ for (index = 0; index < count; ++index)
+ {
+ io_out8 (index_port, index);
+ io_out8 (data_port, values[index]);
+ }
+}
+
+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};
+ volatile u16 *video;
+ volatile u8 *bda;
+ u16 cell;
+ u8 index;
+
+ io_out8 (VGA_MISC_OUTPUT_WRITE, 0x67u);
+
+ io_out8 (VGA_SEQ_INDEX, 0x00u);
+ io_out8 (VGA_SEQ_DATA, 0x01u);
+ for (index = 1; index < 5u; ++index)
+ {
+ io_out8 (VGA_SEQ_INDEX, index);
+ io_out8 (VGA_SEQ_DATA, sequencer[index]);
+ }
+ io_out8 (VGA_SEQ_INDEX, 0x00u);
+ io_out8 (VGA_SEQ_DATA, 0x03u);
+
+ io_out8 (VGA_CRTC_INDEX, 0x11u);
+ io_out8 (VGA_CRTC_DATA, 0x00u);
+ vga_write_registers (VGA_CRTC_INDEX, VGA_CRTC_DATA, crtc, 25);
+
+ vga_write_registers (VGA_GC_INDEX, VGA_GC_DATA, graphics, 9);
+
+ for (index = 0; index < 21u; ++index)
+ {
+ io_in8 (VGA_INPUT_STATUS);
+ io_out8 (VGA_ATTR_INDEX_DATA, index);
+ io_out8 (VGA_ATTR_INDEX_DATA, attributes[index]);
+ }
+
+ io_in8 (VGA_INPUT_STATUS);
+ io_out8 (VGA_ATTR_INDEX_DATA, 0x20u);
+
+ video = (volatile u16 *)VGA_TEXT_BASE;
+ for (cell = 0; cell < VGA_TEXT_CELLS; ++cell)
+ video[cell] = 0x0720u;
+
+ bda = (volatile u8 *)MUBIOS_BDA_BASE;
+ bda[BDA_VIDEO_MODE] = 0x03u;
+ bda[BDA_VIDEO_PAGE] = 0x00u;
+ bda[BDA_VIDEO_COLUMNS] = 80u;
+ bda[BDA_VIDEO_COLUMNS + 1u] = 0u;
+ bda[BDA_VIDEO_PAGE_SIZE] = 0x00u;
+ bda[BDA_VIDEO_PAGE_SIZE + 1u] = 0x10u;
+ *(volatile u16 *)(bda + BDA_CURSOR_BASE) = 0u;
+ *(volatile u16 *)(bda + BDA_CURSOR_SHAPE) = 0x0607u;
+}
diff --git a/mubios/include/bios.h b/mubios/include/bios.h
index 85906d6..c4eb465 100644
--- a/mubios/include/bios.h
+++ b/mubios/include/bios.h
@@ -47,6 +47,7 @@ void serial_write (const char *text);
void pic_init (void);
void pit_init (void);
void ioapic_init (void);
+void vga_text_mode_init (void);
void ivt_init (void);
@@ -59,6 +60,7 @@ struct bios_regs;
void bios_service_dispatch (u8 vector, struct bios_regs *regs);
void int10_service (struct bios_regs *regs);
+void int14_service (struct bios_regs *regs);
void int13_service (struct bios_regs *regs);
void int15_service (struct bios_regs *regs);
void int16_service (struct bios_regs *regs);
diff --git a/mubios/linker.ld b/mubios/linker.ld
index 5dee699..ef45750 100644
--- a/mubios/linker.ld
+++ b/mubios/linker.ld
@@ -26,7 +26,7 @@ ENTRY(reset_entry)
MEMORY
{
ROM (rx) : ORIGIN = 0xF0000, LENGTH = 0x10000
- EBDA (rw) : ORIGIN = 0x9C000, LENGTH = 0x4000
+ EBDA (rw) : ORIGIN = 0x9FC00, LENGTH = 0x0400
}
SECTIONS
diff --git a/mubios/services/int10.c b/mubios/services/int10.c
index 6793c40..4f6aef1 100644
--- a/mubios/services/int10.c
+++ b/mubios/services/int10.c
@@ -63,6 +63,20 @@ int10_service (struct bios_regs *regs)
function = (u8)(regs->eax >> 8);
page = (u8)(regs->ebx >> 8);
+ if (function == 0x00u)
+ {
+ if ((u8)regs->eax == 0x03u)
+ vga_text_mode_init ();
+ return;
+ }
+
+ if (function == 0x0Fu)
+ {
+ regs->eax = (regs->eax & 0xFFFF0000u) | 0x5003u;
+ regs->ebx &= 0xFFFF00FFu;
+ return;
+ }
+
if (function == 0x02u)
{
cursor = int10_cursor_for_page (page);
diff --git a/mubios/services/int14.c b/mubios/services/int14.c
new file mode 100644
index 0000000..86019b7
--- /dev/null
+++ b/mubios/services/int14.c
@@ -0,0 +1,61 @@
+/*
+ RCC-Project
+
+ Copyright (C) 2026 Richard Qin
+
+ This file is part of RCC-Project.
+ */
+
+#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);
+}
+
+void
+int14_service (struct bios_regs *regs)
+{
+ u8 function;
+ u8 status;
+
+ function = (u8)(regs->eax >> 8);
+
+ if (function == 0x00u)
+ {
+ serial_init ();
+ regs->eax &= 0xFFFF0000u;
+ 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;
+ }
+
+ if (function == 0x03u)
+ {
+ status = io_in8 ((u16)(COM1_BASE + COM_LSR));
+ regs->eax = (regs->eax & 0xFFFF00FFu) | ((u32)status << 8);
+ return;
+ }
+
+ regs->eax = 0x0100u;
+}