diff options
| author | Richard Qin <richard.qin.x@gmail.com> | 2026-11-09 03:22:35 +0800 |
|---|---|---|
| committer | Richard Qin <richard.qin.x@gmail.com> | 2026-11-09 03:22:35 +0800 |
| commit | 06cb46aa0236352554f23697e17bed378083be1a (patch) | |
| tree | 099e92dce130d8f3b2bdbe9c88ddc3949babe94c | |
| parent | a54a4236a27e8319da421010fe0c3c5d80edca45 (diff) | |
| download | rcc-project-06cb46aa0236352554f23697e17bed378083be1a.tar.gz rcc-project-06cb46aa0236352554f23697e17bed378083be1a.tar.xz | |
[mubios] Initialize VGA mode and serial BIOS services
| -rw-r--r-- | mubios/arch/interrupt.S | 1 | ||||
| -rw-r--r-- | mubios/core/bda.c | 10 | ||||
| -rw-r--r-- | mubios/core/interrupt.c | 4 | ||||
| -rw-r--r-- | mubios/core/post.c | 1 | ||||
| -rw-r--r-- | mubios/drivers/vga.c | 112 | ||||
| -rw-r--r-- | mubios/include/bios.h | 2 | ||||
| -rw-r--r-- | mubios/linker.ld | 2 | ||||
| -rw-r--r-- | mubios/services/int10.c | 14 | ||||
| -rw-r--r-- | mubios/services/int14.c | 61 |
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; +} |
