aboutsummaryrefslogtreecommitdiff
path: root/mubios/services/int10.c
diff options
context:
space:
mode:
authorRichard Qin <richard.qin.x@gmail.com>2026-11-10 02:29:20 +0800
committerRichard Qin <richard.qin.x@gmail.com>2026-11-10 02:29:20 +0800
commit7ecf4901b486693e525d3daafc7d6e9c3a4abcd0 (patch)
tree722ed5d7919170cedef44bdb22bc87ab98a47682 /mubios/services/int10.c
parent03c2c766aad0746ca3e71b44756b443ae8742e95 (diff)
downloadrcc-project-7ecf4901b486693e525d3daafc7d6e9c3a4abcd0.tar.gz
rcc-project-7ecf4901b486693e525d3daafc7d6e9c3a4abcd0.tar.xz
[mubios] Complete VGA text initialization and add VBE graphics services
Load the 8x16 font and VGA palette, restore text memory mapping, and synchronize BIOS cursor and page state with the hardware. Allocate QEMU standard VGA PCI memory resources and expose VBE controller information, mode queries and switching, logical scanline lengths, and display start control. Signed-off-by: Richard Qin <richard.qin.x@gmail.com>
Diffstat (limited to 'mubios/services/int10.c')
-rw-r--r--mubios/services/int10.c184
1 files changed, 112 insertions, 72 deletions
diff --git a/mubios/services/int10.c b/mubios/services/int10.c
index 4f6aef1..17959be 100644
--- a/mubios/services/int10.c
+++ b/mubios/services/int10.c
@@ -19,136 +19,176 @@
<http://www.gnu.org/licenses/>.
*/
-#include "bios.h"
#include "regs.h"
+#include "vbe.h"
+#include "vga.h"
-#define VGA_TEXT_BASE 0x000B8000u
-#define BDA_CURSOR 0x00000450u
-#define BDA_CURSOR_SHAPE 0x00000460u
-#define VGA_PAGE_SIZE 0x00001000u
-
-static volatile u16 *
+static u16
int10_cursor_for_page (u8 page)
{
- return (volatile u16 *)(BDA_CURSOR + ((u32)page * 2u));
+ return *(volatile u16 *)(MUBIOS_BDA_BASE + BDA_CURSOR_BASE + page * 2u);
}
static volatile u16 *
int10_video_for_page (u8 page)
{
- return (volatile u16 *)(VGA_TEXT_BASE + ((u32)page * VGA_PAGE_SIZE));
+ return (volatile u16 *)(VGA_TEXT_BASE + (u32)page * VGA_PAGE_SIZE);
}
static void
-int10_newline (volatile u16 *cursor)
+int10_teletype (u8 character)
{
- u16 row;
+ volatile u8 *bda = (volatile u8 *)MUBIOS_BDA_BASE;
+ u8 page = bda[BDA_VIDEO_PAGE];
+ volatile u16 *video = int10_video_for_page (page);
+ u16 cursor = int10_cursor_for_page (page);
+ u16 row = cursor >> 8;
+ u16 column = cursor & 0xFFu;
+ u16 position;
+ u16 cell;
+ u16 blank;
+
+ /* AH=0Eh uses the active page, as in SeaVGABIOS. BEL has no text effect. */
+ if (character == 0x07u)
+ return;
+ if (character == 0x0Du)
+ column = 0u;
+ else if (character == 0x0Au)
+ ++row;
+ else if (character == 0x08u)
+ {
+ /* A text-mode backspace moves left without erasing or crossing a row. */
+ if (column != 0u)
+ --column;
+ }
+ else
+ {
+ position = (u16)(row * VGA_COLUMNS + column);
+ /* Mode 03h has 2000 visible cells per page. */
+ if (position >= VGA_TEXT_CELLS)
+ return;
+ video[position] = (u16)((video[position] & 0xFF00u) | character);
+ ++column;
+ if (column >= VGA_COLUMNS)
+ {
+ column = 0u;
+ ++row;
+ }
+ }
- row = (u16)(*cursor / 80u);
- *cursor = (u16)((row + 1u) * 80u);
+ /* Passing the last row scrolls the active page, retaining text attributes.
+ */
+ if (row >= VGA_ROWS)
+ {
+ blank = (u16)((video[(VGA_ROWS - 1u) * VGA_COLUMNS] & 0xFF00u) | 0x20u);
+ for (cell = 0; cell < (VGA_ROWS - 1u) * VGA_COLUMNS; ++cell)
+ video[cell] = video[cell + VGA_COLUMNS];
+ for (; cell < VGA_TEXT_CELLS; ++cell)
+ video[cell] = blank;
+ row = VGA_ROWS - 1u;
+ }
+ vga_set_cursor_position (page, (u16)((row << 8) | column));
}
void
int10_service (struct bios_regs *regs)
{
- volatile u16 *cursor;
+ volatile u8 *bda = (volatile u8 *)MUBIOS_BDA_BASE;
volatile u16 *video;
- u8 function;
- u8 page;
- u8 character;
- u8 attribute;
+ u8 function = (u8)(regs->eax >> 8);
+ u8 page = (u8)(regs->ebx >> 8);
+ u16 cursor;
u16 position;
u16 count;
+ u32 font_address;
- function = (u8)(regs->eax >> 8);
- page = (u8)(regs->ebx >> 8);
+ if (function == 0x4Fu)
+ {
+ vbe_service (regs);
+ return;
+ }
if (function == 0x00u)
{
- if ((u8)regs->eax == 0x03u)
- vga_text_mode_init ();
+ /* Bit 7 preserves video memory; the remaining bits select mode 03h. */
+ if (((u8)regs->eax & 0x7Fu) == 0x03u)
+ vga_text_mode_set ((u8)regs->eax & 0x80u);
return;
}
- if (function == 0x0Fu)
+ if (function == 0x01u)
{
- regs->eax = (regs->eax & 0xFFFF0000u) | 0x5003u;
- regs->ebx &= 0xFFFF00FFu;
+ vga_set_cursor_shape ((u16)regs->ecx);
return;
}
- if (function == 0x02u)
+ if (function == 0x05u)
{
- cursor = int10_cursor_for_page (page);
- position = (u16)(((u8)(regs->edx >> 8) * 80u) + (u8)regs->edx);
- *cursor = position;
+ vga_set_active_page ((u8)regs->eax);
return;
}
- if (function == 0x03u)
+ if (function == 0x0Fu)
{
- cursor = int10_cursor_for_page (page);
- position = *cursor;
- regs->edx = (regs->edx & 0xFFFF0000u) | ((u32)(position / 80u) << 8)
- | (u32)(position % 80u);
- regs->ecx = (regs->ecx & 0xFFFF0000u) | 0x0607u;
+ regs->eax = (regs->eax & 0xFFFF0000u)
+ | ((u32)bda[BDA_VIDEO_COLUMNS] << 8) | bda[BDA_VIDEO_MODE]
+ | (bda[BDA_VIDEO_CTL] & 0x80u);
+ regs->ebx = (regs->ebx & 0xFFFF00FFu) | ((u32)bda[BDA_VIDEO_PAGE] << 8);
return;
}
- if (function != 0x09u && function != 0x0Eu)
- return;
-
- cursor = int10_cursor_for_page (page);
- video = int10_video_for_page (page);
-
- character = (u8)regs->eax;
- attribute = (u8)regs->ebx;
- position = *cursor;
-
- if (function == 0x09u)
+ /* AH=11h/AL=30h reports the current font (BH=1) or ROM 8x16 font (BH=6). */
+ if (function == 0x11u && (u8)regs->eax == 0x30u)
{
- count = (u16)regs->ecx;
-
- while (count != 0u)
+ if (page == 0x01u || page == 0x06u)
{
- if (position >= 2000u)
- position = 0;
-
- video[position] = (u16)character | ((u16)attribute << 8);
- position++;
- count--;
+ font_address = (u32)vga_font_8x16;
+ regs->es = (u16)(font_address >> 4);
+ regs->ebp = (regs->ebp & 0xFFFF0000u) | (font_address & 0x0Fu);
}
-
+ regs->ecx = (regs->ecx & 0xFFFF0000u)
+ | *(volatile u16 *)(bda + BDA_VIDEO_HEIGHT);
+ regs->edx = (regs->edx & 0xFFFFFF00u) | bda[BDA_VIDEO_ROWS];
return;
}
- if (character == 0x0Du)
+ if (function == 0x0Eu)
{
- *cursor = (u16)((position / 80u) * 80u);
+ int10_teletype ((u8)regs->eax);
return;
}
- if (character == 0x0Au)
+ /* The mode 03h INT 10h interface provides page numbers 0 through 7. */
+ if (page >= VGA_PAGE_COUNT)
+ return;
+
+ if (function == 0x02u)
{
- int10_newline (cursor);
+ vga_set_cursor_position (page, (u16)regs->edx);
return;
}
- if (character == 0x08u)
+ if (function == 0x03u)
{
- if (position != 0u)
- {
- position--;
- video[position] = (u16)(0x20u | ((u16)attribute << 8));
- *cursor = position;
- }
-
+ regs->edx = (regs->edx & 0xFFFF0000u) | int10_cursor_for_page (page);
+ regs->ecx = (regs->ecx & 0xFFFF0000u)
+ | *(volatile u16 *)(bda + BDA_CURSOR_SHAPE);
return;
}
- if (position >= 2000u)
- position = 0;
+ if (function != 0x09u)
+ return;
- video[position] = (u16)character | ((u16)attribute << 8);
- *cursor = (u16)(position + 1u);
+ cursor = int10_cursor_for_page (page);
+ position = (u16)((cursor >> 8) * VGA_COLUMNS + (cursor & 0xFFu));
+ video = int10_video_for_page (page);
+ count = (u16)regs->ecx;
+ /* Repeated character/attribute output stays within the visible page and
+ does not change either the BDA or hardware cursor. */
+ while (count != 0u && position < VGA_TEXT_CELLS)
+ {
+ video[position] = (u16)((u8)regs->eax | ((u16)(u8)regs->ebx << 8));
+ ++position;
+ --count;
+ }
}