From 87879e256ffdece5781127fb3b0a9b393bf75afc Mon Sep 17 00:00:00 2001 From: Julian Pidancet Date: Mon, 19 Dec 2011 05:08:00 +0000 Subject: [PATCH] Partially implement VBE interface, create VBE driver skeleton Signed-off-by: Julian Pidancet --- Makefile | 2 +- vgasrc/vbe.c | 142 +++++++++++++++++++++++ vgasrc/vga.c | 276 ++++++++++++++++++++++++++++++++++++++------- vgasrc/vgatables.h | 31 ++++- 4 files changed, 404 insertions(+), 47 deletions(-) create mode 100644 vgasrc/vbe.c diff --git a/Makefile b/Makefile index 4f0e6ab..7ac65fa 100644 --- a/Makefile +++ b/Makefile @@ -170,7 +170,7 @@ $(OUT)bios.bin.elf $(OUT)bios.bin: $(OUT)rom.o tools/checkrom.py # VGA src files SRCVGA=src/output.c src/util.c vgasrc/vga.c vgasrc/vgafb.c vgasrc/vgaio.c \ - vgasrc/vgatables.c vgasrc/vgafonts.c vgasrc/clext.c + vgasrc/vgatables.c vgasrc/vgafonts.c vgasrc/clext.c vgasrc/vbe.c CFLAGS16VGA = $(CFLAGS16INC) -g -Isrc diff --git a/vgasrc/vbe.c b/vgasrc/vbe.c new file mode 100644 index 0000000..b6e0037 --- /dev/null +++ b/vgasrc/vbe.c @@ -0,0 +1,142 @@ +#include "vgatables.h" +#include "vbe.h" + +struct mode +{ + u16 mode; + u16 width; + u16 height; + u8 depth; +} vbe_modes[] VAR16 = { + /* standard modes */ + { 0x100, 640, 400, 8 }, + { 0x101, 640, 480, 8 }, + { 0x102, 800, 600, 4 }, + { 0x103, 800, 600, 8 }, + { 0x104, 1024, 768, 4 }, + { 0x105, 1024, 768, 8 }, + { 0x106, 1280, 1024, 4 }, + { 0x107, 1280, 1024, 8 }, + { 0x10D, 320, 200, 15 }, + { 0x10E, 320, 200, 16 }, + { 0x10F, 320, 200, 24 }, + { 0x110, 640, 480, 15 }, + { 0x111, 640, 480, 16 }, + { 0x112, 640, 480, 24 }, + { 0x113, 800, 600, 15 }, + { 0x114, 800, 600, 16 }, + { 0x115, 800, 600, 24 }, + { 0x116, 1024, 768, 15 }, + { 0x117, 1024, 768, 16 }, + { 0x118, 1024, 768, 24 }, + { 0x119, 1280, 1024, 15 }, + { 0x11A, 1280, 1024, 16 }, + { 0x11B, 1280, 1024, 24 }, + { 0x11C, 1600, 1200, 8 }, + { 0x11D, 1600, 1200, 15 }, + { 0x11E, 1600, 1200, 16 }, + { 0x11F, 1600, 1200, 24 }, + /* BOCHS modes */ + { 0x140, 320, 200, 32 }, + { 0x141, 640, 400, 32 }, + { 0x142, 640, 480, 32 }, + { 0x143, 800, 600, 32 }, + { 0x144, 1024, 768, 32 }, + { 0x145, 1280, 1024, 32 }, + { 0x146, 320, 200, 8 }, + { 0x147, 1600, 1200, 32 }, + { 0x148, 1152, 864, 8 }, + { 0x149, 1152, 864, 15 }, + { 0x14a, 1152, 864, 16 }, + { 0x14b, 1152, 864, 24 }, + { 0x14c, 1152, 864, 32 }, + { 0x178, 1280, 800, 16 }, + { 0x179, 1280, 800, 24 }, + { 0x17a, 1280, 800, 32 }, + { 0x17b, 1280, 960, 16 }, + { 0x17c, 1280, 960, 24 }, + { 0x17d, 1280, 960, 32 }, + { 0x17e, 1440, 900, 16 }, + { 0x17f, 1440, 900, 24 }, + { 0x180, 1440, 900, 32 }, + { 0x181, 1400, 1050, 16 }, + { 0x182, 1400, 1050, 24 }, + { 0x183, 1400, 1050, 32 }, + { 0x184, 1680, 1050, 16 }, + { 0x185, 1680, 1050, 24 }, + { 0x186, 1680, 1050, 32 }, + { 0x187, 1920, 1200, 16 }, + { 0x188, 1920, 1200, 24 }, + { 0x189, 1920, 1200, 32 }, + { 0x18a, 2560, 1600, 16 }, + { 0x18b, 2560, 1600, 24 }, + { 0x18c, 2560, 1600, 32 }, + { 0, }, +}; + +/* Called only during POST */ +int +vbe_init(u8 bus, u8 devfn) +{ + return -1; +} + +int +vbe_enabled(void) +{ + return 0; +} + +u16 +vbe_total_mem(void) +{ + return 0; +} + +int +vbe_list_modes(u16 seg, u16 ptr) +{ + int count = 0; + u16 *dest = (u16 *)(u32)ptr; + + SET_FARVAR(seg, dest[count], 0xffff); /* End of list */ + + return count; +} + +int +vbe_mode_info(u16 mode, struct vbe_modeinfo *info) +{ + return -1; +} + +void +vbe_hires_enable(int enable) +{ + +} + +void +vbe_set_mode(u16 mode, struct vbe_modeinfo *info) +{ + +} + +void +vbe_clear_scr(void) +{ + +} + +int +vbe_hires_enabled(void) +{ + return 0; +} + +u16 +vbe_curr_mode(void) +{ + return 0; +} + diff --git a/vgasrc/vga.c b/vgasrc/vga.c index 3988da9..26f70ce 100644 --- a/vgasrc/vga.c +++ b/vgasrc/vga.c @@ -17,6 +17,7 @@ #include "vgatables.h" // find_vga_entry #include "optionroms.h" // struct pci_data #include "config.h" // CONFIG_* +#include "vbe.h" // vbe_* // XXX #define DEBUG_VGA_POST 1 @@ -358,27 +359,9 @@ restore_bda_state(u16 seg, struct saveBDAstate *info) ****************************************************************/ // set video mode -static void -handle_1000(struct bregs *regs) +void +vga_set_mode(u8 mode, u8 noclearmem) { - u8 noclearmem = regs->al & 0x80; - u8 mode = regs->al & 0x7f; - - // Set regs->al - if (mode > 7) - regs->al = 0x20; - else if (mode == 6) - regs->al = 0x3f; - else - regs->al = 0x30; - - if (CONFIG_VGA_CIRRUS) - cirrus_set_video_mode(mode); - - if (CONFIG_VGA_BOCHS) - if (bochs_has_vbe_display()) - dispi_set_enable(VBE_DISPI_DISABLED); - // find the entry in the video modes struct vgamode_s *vmode_g = find_vga_entry(mode); dprintf(1, "mode search %02x found %p\n", mode, vmode_g); @@ -477,6 +460,29 @@ handle_1000(struct bregs *regs) } } +static void +handle_1000(struct bregs *regs) +{ + u8 noclearmem = regs->al & 0x80; + u8 mode = regs->al & 0x7f; + + // Set regs->al + if (mode > 7) + regs->al = 0x20; + else if (mode == 6) + regs->al = 0x3f; + else + regs->al = 0x30; + + if (CONFIG_VGA_CIRRUS) + cirrus_set_video_mode(mode); + + if (vbe_enabled()) + vbe_hires_enable(0); + + vga_set_mode(mode, noclearmem); +} + static void handle_1001(struct bregs *regs) { @@ -1198,72 +1204,261 @@ handle_101c(struct bregs *regs) } } - static void handle_104f00(struct bregs *regs) { - // XXX - vbe_biosfn_return_controller_information(&AX,ES,DI); - // XXX - OR cirrus_vesa_00h + u16 seg = regs->es; + struct vbe_info *info = (void*)(regs->di+0); + + if (GET_FARVAR(seg, info->signature) == VBE2_SIGNATURE) { + dprintf(4, "Get VBE Controller: VBE2 Signature found\n"); + } else if (GET_FARVAR(seg, info->signature) == VESA_SIGNATURE) { + dprintf(4, "Get VBE Controller: VESA Signature found\n"); + } else { + dprintf(4, "Get VBE Controller: Invalid Signature\n"); + } + + memset_far(seg, info, 0, sizeof(*info)); + + SET_FARVAR(seg, info->signature, VESA_SIGNATURE); + + SET_FARVAR(seg, info->version, 0x0200); + + SET_FARVAR(seg, info->oem_string, + SEGOFF(get_global_seg(), (u32)VBE_OEM_STRING)); + SET_FARVAR(seg, info->capabilities[0], 0x1); /* 8BIT DAC */ + + /* We generate our mode list in the reserved field of the info block */ + SET_FARVAR(seg, info->video_mode, SEGOFF(seg, regs->di + 34)); + + /* Total memory (in 64 blocks) */ + SET_FARVAR(seg, info->total_memory, vbe_total_mem()); + + SET_FARVAR(seg, info->oem_vendor_string, + SEGOFF(get_global_seg(), (u32)VBE_VENDOR_STRING)); + SET_FARVAR(seg, info->oem_product_string, + SEGOFF(get_global_seg(), (u32)VBE_PRODUCT_STRING)); + SET_FARVAR(seg, info->oem_revision_string, + SEGOFF(get_global_seg(), (u32)VBE_REVISION_STRING)); + + /* Fill list of modes */ + vbe_list_modes(seg, regs->di + 32); + + regs->al = regs->ah; /* 0x4F, Function supported */ + regs->ah = 0x0; /* 0x0, Function call successful */ } static void handle_104f01(struct bregs *regs) { - // XXX - vbe_biosfn_return_mode_information(&AX,CX,ES,DI); - // XXX - OR cirrus_vesa_01h + u16 seg = regs->es; + struct vbe_mode_info *info = (void*)(regs->di+0); + u16 mode = regs->cx; + struct vbe_modeinfo modeinfo; + int rc; + + dprintf(1, "VBE mode info request: %x\n", mode); + + rc = vbe_mode_info(mode, &modeinfo); + if (rc) { + dprintf(1, "VBE mode %x not found\n", mode); + regs->ax = 0x100; + return; + } + + u16 mode_attr = VBE_MODE_ATTRIBUTE_SUPPORTED | + VBE_MODE_ATTRIBUTE_EXTENDED_INFORMATION_AVAILABLE | + VBE_MODE_ATTRIBUTE_COLOR_MODE | + VBE_MODE_ATTRIBUTE_GRAPHICS_MODE; + if (modeinfo.depth == 4) + mode_attr |= VBE_MODE_ATTRIBUTE_TTY_BIOS_SUPPORT; + else + mode_attr |= VBE_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER_MODE; + SET_FARVAR(seg, info->mode_attributes, mode_attr); + SET_FARVAR(seg, info->winA_attributes, + VBE_WINDOW_ATTRIBUTE_RELOCATABLE | + VBE_WINDOW_ATTRIBUTE_READABLE | + VBE_WINDOW_ATTRIBUTE_WRITEABLE); + SET_FARVAR(seg, info->winB_attributes, 0); + SET_FARVAR(seg, info->win_granularity, 64); /* Bank size 64K */ + SET_FARVAR(seg, info->win_size, 64); /* Bank size 64K */ + SET_FARVAR(seg, info->winA_seg, 0xA000); + SET_FARVAR(seg, info->winB_seg, 0x0); + SET_FARVAR(seg, info->win_func_ptr, 0x0); + SET_FARVAR(seg, info->bytes_per_scanline, modeinfo.linesize); + SET_FARVAR(seg, info->xres, modeinfo.width); + SET_FARVAR(seg, info->yres, modeinfo.height); + SET_FARVAR(seg, info->xcharsize, 8); + SET_FARVAR(seg, info->ycharsize, 16); + if (modeinfo.depth == 4) + SET_FARVAR(seg, info->planes, 4); + else + SET_FARVAR(seg, info->planes, 1); + SET_FARVAR(seg, info->bits_per_pixel, modeinfo.depth); + SET_FARVAR(seg, info->banks, + (modeinfo.linesize * modeinfo.height + 65535) / 65536); + if (modeinfo.depth == 4) + SET_FARVAR(seg, info->mem_model, VBE_MEMORYMODEL_PLANAR); + else if (modeinfo.depth == 8) + SET_FARVAR(seg, info->mem_model, VBE_MEMORYMODEL_PACKED_PIXEL); + else + SET_FARVAR(seg, info->mem_model, VBE_MEMORYMODEL_DIRECT_COLOR); + SET_FARVAR(seg, info->bank_size, 0); + u32 pages = modeinfo.vram_size / (modeinfo.height * modeinfo.linesize); + if (modeinfo.depth == 4) + SET_FARVAR(seg, info->pages, (pages / 4) - 1); + else + SET_FARVAR(seg, info->pages, pages - 1); + SET_FARVAR(seg, info->reserved0, 1); + + u8 r_size, r_pos, g_size, g_pos, b_size, b_pos, a_size, a_pos; + + switch (modeinfo.depth) { + case 15: r_size = 5; r_pos = 10; g_size = 5; g_pos = 5; + b_size = 5; b_pos = 0; a_size = 1; a_pos = 15; break; + case 16: r_size = 5; r_pos = 11; g_size = 6; g_pos = 5; + b_size = 5; b_pos = 0; a_size = 0; a_pos = 0; break; + case 24: r_size = 8; r_pos = 16; g_size = 8; g_pos = 8; + b_size = 8; b_pos = 0; a_size = 0; a_pos = 0; break; + case 32: r_size = 8; r_pos = 16; g_size = 8; g_pos = 8; + b_size = 8; b_pos = 0; a_size = 8; a_pos = 24; break; + default: r_size = 0; r_pos = 0; g_size = 0; g_pos = 0; + b_size = 0; b_pos = 0; a_size = 0; a_pos = 0; break; + } + + SET_FARVAR(seg, info->red_size, r_size); + SET_FARVAR(seg, info->red_pos, r_pos); + SET_FARVAR(seg, info->green_size, g_size); + SET_FARVAR(seg, info->green_pos, g_pos); + SET_FARVAR(seg, info->blue_size, b_size); + SET_FARVAR(seg, info->blue_pos, b_pos); + SET_FARVAR(seg, info->alpha_size, a_size); + SET_FARVAR(seg, info->alpha_pos, a_pos); + + if (modeinfo.depth == 32) + SET_FARVAR(seg, info->directcolor_info, + VBE_DIRECTCOLOR_RESERVED_BITS_AVAILABLE); + else + SET_FARVAR(seg, info->directcolor_info, 0); + + if (modeinfo.depth > 4) + SET_FARVAR(seg, info->phys_base, modeinfo.phys_base); + else + SET_FARVAR(seg, info->phys_base, 0); + + SET_FARVAR(seg, info->reserved1, 0); + SET_FARVAR(seg, info->reserved2, 0); + SET_FARVAR(seg, info->linear_bytes_per_scanline, modeinfo.linesize); + SET_FARVAR(seg, info->bank_pages, 0); + SET_FARVAR(seg, info->linear_pages, 0); + SET_FARVAR(seg, info->linear_red_size, r_size); + SET_FARVAR(seg, info->linear_red_pos, r_pos); + SET_FARVAR(seg, info->linear_green_size, g_size); + SET_FARVAR(seg, info->linear_green_pos, g_pos); + SET_FARVAR(seg, info->linear_blue_size, b_size); + SET_FARVAR(seg, info->linear_blue_pos, b_pos); + SET_FARVAR(seg, info->linear_alpha_size, a_size); + SET_FARVAR(seg, info->linear_alpha_pos, a_pos); + SET_FARVAR(seg, info->pixclock_max, 0); + + regs->al = regs->ah; /* 0x4F, Function supported */ + regs->ah = 0x0; /* 0x0, Function call successful */ } static void handle_104f02(struct bregs *regs) { - // XXX - vbe_biosfn_set_mode(&AX,BX,ES,DI); - // XXX - OR cirrus_vesa_02h + //u16 seg = regs->es; + //struct vbe_crtc_info *crtc_info = (void*)(regs->di+0); + u16 mode = regs->bx; + struct vbe_modeinfo modeinfo; + int rc; + + dprintf(1, "VBE mode set: %x\n", mode); + + if (mode < 0x100) { /* VGA */ + dprintf(1, "set VGA mode %x\n", mode); + + vbe_hires_enable(0); + vga_set_mode(mode, 0); + } else { /* VBE */ + rc = vbe_mode_info(mode & 0x1ff, &modeinfo); + if (rc) { + dprintf(1, "VBE mode %x not found\n", mode & 0x1ff); + regs->ax = 0x100; + return; + } + vbe_hires_enable(1); + vbe_set_mode(mode & 0x1ff, &modeinfo); + + if (mode & 0x4000) { + /* Linear frame buffer */ + /* XXX: ??? */ + } + if (!(mode & 0x8000)) { + vbe_clear_scr(); + } + } + + regs->al = regs->ah; /* 0x4F, Function supported */ + regs->ah = 0x0; /* 0x0, Function call successful */ } static void handle_104f03(struct bregs *regs) { - // XXX - vbe_biosfn_return_current_mode - // XXX - OR cirrus_vesa_03h + if (!vbe_hires_enabled()) { + regs->bx = GET_BDA(video_mode); + } else { + regs->bx = vbe_curr_mode(); + } + + dprintf(1, "VBE current mode=%x\n", regs->bx); + + regs->al = regs->ah; /* 0x4F, Function supported */ + regs->ah = 0x0; /* 0x0, Function call successful */ } static void handle_104f04(struct bregs *regs) { - // XXX - vbe_biosfn_save_restore_state(&AX, CX, DX, ES, &BX); + debug_enter(regs, DEBUG_VGA_10); + regs->ax = 0x0100; } static void handle_104f05(struct bregs *regs) { - // XXX - vbe_biosfn_display_window_control - // XXX - OR cirrus_vesa_05h + debug_enter(regs, DEBUG_VGA_10); + regs->ax = 0x0100; } static void handle_104f06(struct bregs *regs) { - // XXX - vbe_biosfn_set_get_logical_scan_line_length - // XXX - OR cirrus_vesa_06h + debug_enter(regs, DEBUG_VGA_10); + regs->ax = 0x0100; } static void handle_104f07(struct bregs *regs) { - // XXX - vbe_biosfn_set_get_display_start - // XXX - OR cirrus_vesa_07h + debug_enter(regs, DEBUG_VGA_10); + regs->ax = 0x0100; } static void handle_104f08(struct bregs *regs) { - // XXX - vbe_biosfn_set_get_dac_palette_format + debug_enter(regs, DEBUG_VGA_10); + regs->ax = 0x0100; } static void handle_104f0a(struct bregs *regs) { - // XXX - vbe_biosfn_return_protected_mode_interface + debug_enter(regs, DEBUG_VGA_10); + regs->ax = 0x0100; } static void @@ -1276,7 +1471,7 @@ handle_104fXX(struct bregs *regs) static void handle_104f(struct bregs *regs) { - if (! CONFIG_VGA_BOCHS || !bochs_has_vbe_display()) { + if (!vbe_enabled()) { handle_104fXX(regs); return; } @@ -1377,8 +1572,7 @@ vga_post(struct bregs *regs) init_bios_area(); - if (CONFIG_VGA_BOCHS) - bochs_init(); + vbe_init(regs->ah, regs->al); extern void entry_10(void); SET_IVT(0x10, SEGOFF(get_global_seg(), (u32)entry_10)); diff --git a/vgasrc/vgatables.h b/vgasrc/vgatables.h index 1f877c5..5c0f3bf 100644 --- a/vgasrc/vgatables.h +++ b/vgasrc/vgatables.h @@ -156,6 +156,7 @@ struct carattr { struct cursorpos { u8 x, y, page; }; +void vga_set_mode(u8 mode, u8 noclearmem); // vgafb.c void clear_screen(struct vgamode_s *vmode_g); @@ -208,10 +209,30 @@ void vgahw_init(void); void cirrus_set_video_mode(u8 mode); void cirrus_init(void); -// vbe.c -- not implemented yet. -#define VBE_DISPI_DISABLED 0x00 -void dispi_set_enable(int enable); -void bochs_init(void); -int bochs_has_vbe_display(void); +// vbe.c +#define VBE_OEM_STRING "SeaBIOS VBE(C) 2011" +#define VBE_VENDOR_STRING "SeaBIOS Developers" +#define VBE_PRODUCT_STRING "SeaBIOS VBE Adapter" +#define VBE_REVISION_STRING "Rev. 1" + +struct vbe_modeinfo +{ + u16 width; + u16 height; + u8 depth; + u16 linesize; + u32 phys_base; + u32 vram_size; +}; +int vbe_init(u8 bus, u8 devfn); +int vbe_enabled(void); +u16 vbe_total_mem(void); +int vbe_list_modes(u16 seg, u16 ptr); +int vbe_mode_info(u16 mode, struct vbe_modeinfo *info); +void vbe_hires_enable(int enable); +void vbe_set_mode(u16 mode, struct vbe_modeinfo *info); +void vbe_clear_scr(void); +int vbe_hires_enabled(void); +u16 vbe_curr_mode(void); #endif // vgatables.h -- 2.25.1