The boot menu no longer changes the meaning of the default video mode once

you choose it in the menu.
The boot loader now always switches into a graphics mode unless it's in
debug mode (currently triggered by pressing the escape key on startup).
That means, "Standard VGA" now actually means mode 0x12 (640x480x4)
instead of text mode.
Since the current limited boot logo code would do stupid things with VGA
planes, there will now only be some colored blocks visible during boot.
Implemented support for monochrome modes in the frame buffer console.
Additionally, the frame buffer console now has support for the VGA mode; it
will treat all 4 bit modes as monochrome for now (the VGA 0x12 mode is a
planar mode so this works nicely).


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@12235 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2005-04-04 16:56:18 +00:00
parent 56aa0c51dc
commit d3ff9cc39a
3 changed files with 249 additions and 79 deletions
+38
View File
@@ -0,0 +1,38 @@
/*
* Copyright 2005, Axel Dörfler, [email protected]. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef VGA_H
#define VGA_H
/* VGA ports */
// misc stuff
#define VGA_INPUT_STATUS_0 0x3c2
#define VGA_INPUT_STATUS_1 0x3da
// sequencer registers
#define VGA_SEQUENCER_INDEX 0x3c4
#define VGA_SEQUENCER_DATA 0x3c5
// graphics registers
#define VGA_GRAPHICS_INDEX 0x3ce
#define VGA_GRAPHICS_DATA 0x3cf
// CRTC registers
#define VGA_CRTC_INDEX 0x3d4
#define VGA_CRTC_DATA 0x3d5
// attribute registers
#define VGA_ATTRIBUTE_READ 0x3c1
#define VGA_ATTRIBUTE_WRITE 0x3c0
// color registers
#define VGA_COLOR_STATE 0x3c7
#define VGA_COLOR_READ_MODE 0x3c7
#define VGA_COLOR_WRITE_MODE 0x3c8
#define VGA_COLOR_DATA 0x3c9
#define VGA_COLOR_MASK 0x3c6
#endif /* VGA_H */
+118 -41
View File
@@ -7,6 +7,7 @@
#include "video.h" #include "video.h"
#include "bios.h" #include "bios.h"
#include "vesa.h" #include "vesa.h"
#include "vga.h"
#include "mmu.h" #include "mmu.h"
#include "images.h" #include "images.h"
@@ -37,7 +38,7 @@ struct video_mode {
}; };
static vbe_info_block sInfo; static vbe_info_block sInfo;
static video_mode *sMode; static video_mode *sMode, *sDefaultMode;
static bool sVesaCompatible; static bool sVesaCompatible;
struct list sModeList; struct list sModeList;
static addr_t sFrameBuffer; static addr_t sFrameBuffer;
@@ -48,13 +49,13 @@ static bool sSettingsLoaded;
static void static void
vga_set_palette(const uint8 *palette, int32 firstIndex, int32 numEntries) vga_set_palette(const uint8 *palette, int32 firstIndex, int32 numEntries)
{ {
out8(firstIndex, 0x03c8); out8(firstIndex, VGA_COLOR_WRITE_MODE);
// write VGA palette // write VGA palette
for (int32 i = firstIndex; i < numEntries; i++) { for (int32 i = firstIndex; i < numEntries; i++) {
// VGA (usually) has only 6 bits per gun // VGA (usually) has only 6 bits per gun
out8(palette[i * 3 + 0] >> 2, 0x03c9); out8(palette[i * 3 + 0] >> 2, VGA_COLOR_DATA);
out8(palette[i * 3 + 1] >> 2, 0x03c9); out8(palette[i * 3 + 1] >> 2, VGA_COLOR_DATA);
out8(palette[i * 3 + 2] >> 2, 0x03c9); out8(palette[i * 3 + 2] >> 2, VGA_COLOR_DATA);
} }
} }
@@ -63,14 +64,14 @@ static void
vga_enable_bright_background_colors(void) vga_enable_bright_background_colors(void)
{ {
// reset attribute controller // reset attribute controller
in8(0x03da); in8(VGA_INPUT_STATUS_1);
// select mode control register // select mode control register
out8(0x30, 0x03c0); out8(0x30, VGA_ATTRIBUTE_WRITE);
// read mode control register, change it (we need to clear bit 3), and write it back // read mode control register, change it (we need to clear bit 3), and write it back
uint8 mode = in8(0x03c1) & 0xf7; uint8 mode = in8(VGA_ATTRIBUTE_READ) & 0xf7;
out8(mode, 0x3c0); out8(mode, VGA_ATTRIBUTE_WRITE);
} }
@@ -280,8 +281,22 @@ video_mode_hook(Menu *menu, MenuItem *item)
menu = item->Submenu(); menu = item->Submenu();
item = menu->FindMarked(); item = menu->FindMarked();
if (item != NULL) if (item != NULL) {
switch (menu->IndexOf(item)) {
case 0:
// "Default" mode special
sMode = sDefaultMode;
sModeChosen = false;
return true;
case 1:
// "Standard VGA" mode special
// sets sMode to NULL which triggers VGA mode
break;
default:
mode = (video_mode *)item->Data(); mode = (video_mode *)item->Data();
break;
}
}
if (mode != sMode) { if (mode != sMode) {
// update standard mode // update standard mode
@@ -384,9 +399,20 @@ out:
} }
static void
set_vga_mode(void)
{
// sets 640x480 16 colors graphics mode
bios_regs regs;
regs.eax = 0x12;
call_bios(0x10, &regs);
}
static void static void
set_text_mode(void) set_text_mode(void)
{ {
// sets 80x25 text console
bios_regs regs; bios_regs regs;
regs.eax = 3; regs.eax = 3;
call_bios(0x10, &regs); call_bios(0x10, &regs);
@@ -403,26 +429,22 @@ platform_switch_to_logo(void)
if ((platform_boot_options() & BOOT_OPTION_DEBUG_OUTPUT) != 0) if ((platform_boot_options() & BOOT_OPTION_DEBUG_OUTPUT) != 0)
return; return;
if (!sVesaCompatible || sMode == NULL) addr_t lastBase = gKernelArgs.frame_buffer.physical_buffer.start;
// no logo for now... size_t lastSize = gKernelArgs.frame_buffer.physical_buffer.size;
return; int32 bytesPerPixel = 1;
if (sVesaCompatible && sMode != NULL) {
if (!sModeChosen) if (!sModeChosen)
get_mode_from_settings(); get_mode_from_settings();
if (vesa_set_mode(sMode->mode) != B_OK) if (vesa_set_mode(sMode->mode) != B_OK)
return; goto fallback;
gKernelArgs.frame_buffer.enabled = 1;
struct vbe_mode_info modeInfo; struct vbe_mode_info modeInfo;
if (vesa_get_mode_info(sMode->mode, &modeInfo) != B_OK) { if (vesa_get_mode_info(sMode->mode, &modeInfo) != B_OK)
platform_switch_to_text_mode(); goto fallback;
return;
}
addr_t lastBase = gKernelArgs.frame_buffer.physical_buffer.start; bytesPerPixel = (modeInfo.bits_per_pixel + 7) / 8;
int32 bytesPerPixel = (modeInfo.bits_per_pixel + 7) / 8;
gKernelArgs.frame_buffer.width = modeInfo.width; gKernelArgs.frame_buffer.width = modeInfo.width;
gKernelArgs.frame_buffer.height = modeInfo.height; gKernelArgs.frame_buffer.height = modeInfo.height;
@@ -430,36 +452,45 @@ platform_switch_to_logo(void)
gKernelArgs.frame_buffer.physical_buffer.size = gKernelArgs.frame_buffer.width gKernelArgs.frame_buffer.physical_buffer.size = gKernelArgs.frame_buffer.width
* gKernelArgs.frame_buffer.height * bytesPerPixel; * gKernelArgs.frame_buffer.height * bytesPerPixel;
gKernelArgs.frame_buffer.physical_buffer.start = modeInfo.physical_base; gKernelArgs.frame_buffer.physical_buffer.start = modeInfo.physical_base;
} else {
fallback:
// use standard VGA mode 640x480x4
set_vga_mode();
// ToDo: we assume that physical base is constant through the different resolutions gKernelArgs.frame_buffer.width = 640;
// ToDo: this is broken - if the newly chosen video mode is larger than the old one gKernelArgs.frame_buffer.height = 480;
// the boot loader will crash while trying to access unmapped memory gKernelArgs.frame_buffer.depth = 4;
gKernelArgs.frame_buffer.physical_buffer.size = gKernelArgs.frame_buffer.width
* gKernelArgs.frame_buffer.height / 2;
gKernelArgs.frame_buffer.physical_buffer.start = 0xa0000;
}
gKernelArgs.frame_buffer.enabled = 1;
// If the new frame buffer is either larger than the old one or located at
// a different address, we need to remap it, so we first have to throw
// away its previous mapping
if (lastBase != 0
&& (lastBase != gKernelArgs.frame_buffer.physical_buffer.start
|| lastSize < gKernelArgs.frame_buffer.physical_buffer.size)) {
mmu_free((void *)sFrameBuffer, lastSize);
lastBase = 0;
}
if (lastBase == 0) { if (lastBase == 0) {
// the graphics memory has not been mapped yet! // the graphics memory has not been mapped yet!
sFrameBuffer = mmu_map_physical_memory(modeInfo.physical_base, sFrameBuffer = mmu_map_physical_memory(gKernelArgs.frame_buffer.physical_buffer.start,
gKernelArgs.frame_buffer.physical_buffer.size, 0x03); gKernelArgs.frame_buffer.physical_buffer.size, 0x03);
} }
// clear the video memory // clear the video memory
// ToDo: this shouldn't be necessary on real hardware (and Bochs), but // ToDo: this shouldn't be necessary on real hardware (and Bochs), but
// at least booting with Qemu looks ugly when this is missing // at least booting with Qemu looks ugly when this is missing
memset((void *)sFrameBuffer, 0, gKernelArgs.frame_buffer.physical_buffer.size); //memset((void *)sFrameBuffer, 0, gKernelArgs.frame_buffer.physical_buffer.size);
if (sMode != NULL) {
if (vesa_set_palette((const uint8 *)kPalette, 0, 256) != B_OK) if (vesa_set_palette((const uint8 *)kPalette, 0, 256) != B_OK)
dprintf("set palette failed!\n"); dprintf("set palette failed!\n");
#if 0
uint8 *bits = (uint8 *)gKernelArgs.fb.mapping.start;
uint32 bytesPerRow = gKernelArgs.fb.x_size;
for (int32 y = 10; y < 30; y++) {
for (int32 i = 0; i < 256; i++) {
bits[y * bytesPerRow + i * 3] = i;
bits[y * bytesPerRow + i * 3 + 1] = i;
bits[y * bytesPerRow + i * 3 + 2] = i;
}
}
#endif
// ToDo: this is a temporary hack! // ToDo: this is a temporary hack!
addr_t start = sFrameBuffer + gKernelArgs.frame_buffer.width addr_t start = sFrameBuffer + gKernelArgs.frame_buffer.width
* (gKernelArgs.frame_buffer.height - kHeight - 60) * (gKernelArgs.frame_buffer.height - kHeight - 60)
@@ -468,6 +499,50 @@ platform_switch_to_logo(void)
memcpy((void *)(start + gKernelArgs.frame_buffer.width * i), memcpy((void *)(start + gKernelArgs.frame_buffer.width * i),
&kImageData[i * kWidth], kWidth); &kImageData[i * kWidth], kWidth);
} }
} else {
// vga_set_palette((const uint8 *)kPalette16, 0, 16);
// ToDo: no boot logo yet in VGA mode
#if 1
// this draws 16 big rectangles in all the available colors
uint8 *bits = (uint8 *)sFrameBuffer;
uint32 bytesPerRow = 80;
for (int32 i = 0; i < 32; i++) {
bits[9 * bytesPerRow + i + 2] = 0x55;
bits[30 * bytesPerRow + i + 2] = 0xaa;
}
for (int32 y = 10; y < 30; y++) {
for (int32 i = 0; i < 16; i++) {
out16((15 << 8) | 0x02, VGA_SEQUENCER_INDEX);
bits[32 * bytesPerRow + i*2 + 2] = i;
if (i & 1) {
out16((1 << 8) | 0x02, VGA_SEQUENCER_INDEX);
bits[y * bytesPerRow + i*2 + 2] = 0xff;
bits[y * bytesPerRow + i*2 + 3] = 0xff;
}
if (i & 2) {
out16((2 << 8) | 0x02, VGA_SEQUENCER_INDEX);
bits[y * bytesPerRow + i*2 + 2] = 0xff;
bits[y * bytesPerRow + i*2 + 3] = 0xff;
}
if (i & 4) {
out16((4 << 8) | 0x02, VGA_SEQUENCER_INDEX);
bits[y * bytesPerRow + i*2 + 2] = 0xff;
bits[y * bytesPerRow + i*2 + 3] = 0xff;
}
if (i & 8) {
out16((8 << 8) | 0x02, VGA_SEQUENCER_INDEX);
bits[y * bytesPerRow + i*2 + 2] = 0xff;
bits[y * bytesPerRow + i*2 + 3] = 0xff;
}
}
}
// enable all planes again
out16((15 << 8) | 0x02, VGA_SEQUENCER_INDEX);
#endif
}
} }
@@ -497,14 +572,16 @@ platform_init_video(void)
// Obviously, some graphics card BIOS implementations don't // Obviously, some graphics card BIOS implementations don't
// report all available modes unless you've done this before // report all available modes unless you've done this before
// getting the VESA information. // getting the VESA information.
// One example of those is the SiS 630 chipset on my laptop. // One example of those is the SiS 630 chipset in my laptop.
sVesaCompatible = vesa_init(&sInfo, &sMode) == B_OK; sVesaCompatible = vesa_init(&sInfo, &sDefaultMode) == B_OK;
if (!sVesaCompatible) { if (!sVesaCompatible) {
TRACE(("No VESA compatible graphics!\n")); TRACE(("No VESA compatible graphics!\n"));
return B_ERROR; return B_ERROR;
} }
sMode = sDefaultMode;
TRACE(("VESA compatible graphics!\n")); TRACE(("VESA compatible graphics!\n"));
return B_OK; return B_OK;
+57 -2
View File
@@ -100,6 +100,7 @@ get_palette_entry(uint8 index)
static void static void
render_glyph(int32 x, int32 y, uint8 glyph, uint8 attr) render_glyph(int32 x, int32 y, uint8 glyph, uint8 attr)
{ {
if (sConsole.depth >= 8) {
uint8 *base = (uint8 *)(sConsole.frame_buffer + sConsole.bytes_per_row * y * CHAR_HEIGHT uint8 *base = (uint8 *)(sConsole.frame_buffer + sConsole.bytes_per_row * y * CHAR_HEIGHT
+ x * CHAR_WIDTH * sConsole.bytes_per_pixel); + x * CHAR_WIDTH * sConsole.bytes_per_pixel);
uint8 *color = get_palette_entry(foreground_color(attr)); uint8 *color = get_palette_entry(foreground_color(attr));
@@ -119,6 +120,36 @@ render_glyph(int32 x, int32 y, uint8 glyph, uint8 attr)
base += sConsole.bytes_per_row; base += sConsole.bytes_per_row;
} }
} else {
// monochrome mode
uint8 *base = (uint8 *)(sConsole.frame_buffer + sConsole.bytes_per_row * y * CHAR_HEIGHT
+ x * CHAR_WIDTH / 8);
uint8 baseOffset = (x * CHAR_WIDTH) & 0x7;
for (y = 0; y < CHAR_HEIGHT; y++) {
uint8 bits = FONT[CHAR_HEIGHT * glyph + y];
uint8 offset = baseOffset;
uint8 mask = 1 << (7 - baseOffset);
for (x = 0; x < CHAR_WIDTH; x++) {
if (mask == 0)
mask = 128;
// black on white
if (bits & 1)
base[offset / 8] &= ~mask;
else
base[offset / 8] |= mask;
bits >>= 1;
mask >>= 1;
offset += 1;
}
base += sConsole.bytes_per_row;
}
}
} }
@@ -134,6 +165,11 @@ draw_cursor(int32 x, int32 y)
int32 endY = y + CHAR_HEIGHT; int32 endY = y + CHAR_HEIGHT;
uint8 *base = (uint8 *)(sConsole.frame_buffer + y * sConsole.bytes_per_row); uint8 *base = (uint8 *)(sConsole.frame_buffer + y * sConsole.bytes_per_row);
if (sConsole.depth < 8) {
x /= 8;
endY /= 8;
}
for (; y < endY; y++) { for (; y < endY; y++) {
for (int32 x2 = x; x2 < endX; x2++) for (int32 x2 = x; x2 < endX; x2++)
base[x2] = ~base[x2]; base[x2] = ~base[x2];
@@ -200,11 +236,19 @@ static void
console_blit(int32 srcx, int32 srcy, int32 width, int32 height, int32 destx, int32 desty) console_blit(int32 srcx, int32 srcy, int32 width, int32 height, int32 destx, int32 desty)
{ {
height *= CHAR_HEIGHT; height *= CHAR_HEIGHT;
srcy *= CHAR_HEIGHT;
desty *= CHAR_HEIGHT;
if (sConsole.depth >= 8) {
width *= CHAR_WIDTH * sConsole.bytes_per_pixel; width *= CHAR_WIDTH * sConsole.bytes_per_pixel;
srcx *= CHAR_WIDTH * sConsole.bytes_per_pixel; srcx *= CHAR_WIDTH * sConsole.bytes_per_pixel;
srcy *= CHAR_HEIGHT;
destx *= CHAR_WIDTH * sConsole.bytes_per_pixel; destx *= CHAR_WIDTH * sConsole.bytes_per_pixel;
desty *= CHAR_HEIGHT; } else {
// monochrome mode
width = width * CHAR_WIDTH / 8;
srcx = srcx * CHAR_WIDTH / 8;
destx = destx * CHAR_WIDTH / 8;
}
for (int32 y = 0; y < height; y++) { for (int32 y = 0; y < height; y++) {
memmove((void *)(sConsole.frame_buffer + (desty + y) * sConsole.bytes_per_row + destx), memmove((void *)(sConsole.frame_buffer + (desty + y) * sConsole.bytes_per_row + destx),
@@ -218,8 +262,14 @@ console_clear(uint8 attr)
{ {
switch (sConsole.bytes_per_pixel) { switch (sConsole.bytes_per_pixel) {
case 1: case 1:
if (sConsole.depth >= 8) {
memset((void *)sConsole.frame_buffer, sPalette8[background_color(attr)], memset((void *)sConsole.frame_buffer, sPalette8[background_color(attr)],
sConsole.height * sConsole.bytes_per_row); sConsole.height * sConsole.bytes_per_row);
} else {
// special case for VGA mode
memset((void *)sConsole.frame_buffer, 0xff,
sConsole.height * sConsole.bytes_per_row);
}
break; break;
default: default:
{ {
@@ -323,6 +373,11 @@ frame_buffer_console_init(kernel_args *args)
int32 bytesPerRow = args->frame_buffer.width; int32 bytesPerRow = args->frame_buffer.width;
switch (args->frame_buffer.depth) { switch (args->frame_buffer.depth) {
case 1:
case 4:
// special VGA mode (will always be treated as monochrome)
bytesPerRow /= 8;
break;
case 15: case 15:
case 16: case 16:
bytesPerRow *= 2; bytesPerRow *= 2;