From Adrien Destugues <pulkomandy@xxxxxxxxx>:
Adrien Destugues has uploaded this change for review. (
https://review.haiku-os.org/c/haiku/+/4650 ;)
Change subject: vesa: move patching code to a separate file.
......................................................................
vesa: move patching code to a separate file.
---
M src/add-ons/kernel/drivers/graphics/vesa/Jamfile
A src/add-ons/kernel/drivers/graphics/vesa/patch.cpp
M src/add-ons/kernel/drivers/graphics/vesa/vesa.cpp
M src/add-ons/kernel/drivers/graphics/vesa/vesa_private.h
4 files changed, 479 insertions(+), 446 deletions(-)
git pull ssh://git.haiku-os.org:22/haiku refs/changes/50/4650/1
diff --git a/src/add-ons/kernel/drivers/graphics/vesa/Jamfile
b/src/add-ons/kernel/drivers/graphics/vesa/Jamfile
index 8745574..32c0cec 100644
--- a/src/add-ons/kernel/drivers/graphics/vesa/Jamfile
+++ b/src/add-ons/kernel/drivers/graphics/vesa/Jamfile
@@ -10,6 +10,7 @@
KernelAddon vesa :
device.cpp
driver.cpp
+ patch.cpp
vesa.cpp
vga.cpp
;
diff --git a/src/add-ons/kernel/drivers/graphics/vesa/patch.cpp
b/src/add-ons/kernel/drivers/graphics/vesa/patch.cpp
new file mode 100644
index 0000000..7ae2bc5
--- /dev/null
+++ b/src/add-ons/kernel/drivers/graphics/vesa/patch.cpp
@@ -0,0 +1,464 @@
+/*
+ * Copyright 2021, Adrien Destugues, pulkomandy@xxxxxxxxxxxxx
+ * Distributed under the terms of the MIT License.
+ */
+
+
+#include "vesa_private.h"
+#include "vesa.h"
+
+#include <SupportDefs.h>
+
+#define _GNU_SOURCE
+#include <string.h>
+
+#include "atombios.h"
+#include "driver.h"
+#include "edid_raw.h"
+#include "utility.h"
+#include "vesa_info.h"
+
+
+extern bios_module_info* sBIOSModule;
+status_t vbe_call_prepare(bios_state** state);
+status_t vbe_get_mode_info(bios_state* state, uint16 mode, struct
vbe_mode_info* modeInfo);
+uint32 get_color_space_for_depth(uint32 depth);
+status_t vbe_set_mode(bios_state* state, uint16 mode);
+status_t vbe_set_bits_per_gun(bios_state* state, vesa_info& info, uint8 bits);
+status_t remap_frame_buffer(vesa_info& info, addr_t physicalBase, uint32 width,
+ uint32 height, int8 depth, uint32 bytesPerRow, bool initializing);
+void vbe_call_finish(bios_state* state);
+
+
+status_t
+vbe_patch_intel_bios(bios_state* state, display_mode& mode)
+{
+ edid1_detailed_timing_raw timing;
+
+ timing.pixel_clock = mode.timing.pixel_clock / 10;
+
+ timing.h_active = mode.timing.h_display & 0xFF;
+ timing.h_active_high = (mode.timing.h_display >> 8) & 0xF;
+
+ uint16 h_blank = mode.timing.h_total - mode.timing.h_display;
+ timing.h_blank = h_blank & 0xff;
+ timing.h_blank_high = (h_blank >> 8) & 0xF;
+
+ timing.v_active = mode.timing.v_display & 0xFF;
+ timing.v_active_high = (mode.timing.v_display >> 8) & 0xF;
+
+ uint16 v_blank = mode.timing.v_total - mode.timing.v_display;
+ timing.v_blank = v_blank & 0xff;
+ timing.v_blank_high = (v_blank >> 8) & 0xF;
+
+ uint16 h_sync_off = mode.timing.h_sync_start - mode.timing.h_display;
+ timing.h_sync_off = h_sync_off & 0xFF;
+ timing.h_sync_off_high = (h_sync_off >> 8) & 0x3;
+
+ uint16 h_sync_width = mode.timing.h_sync_end - mode.timing.h_sync_start;
+ timing.h_sync_width = h_sync_width & 0xFF;
+ timing.h_sync_width_high = (h_sync_width >> 8) & 0x3;
+
+ uint16 v_sync_off = mode.timing.v_sync_start - mode.timing.v_display;
+ timing.v_sync_off = v_sync_off & 0xF;
+ timing.v_sync_off_high = (v_sync_off >> 4) & 0x3;
+
+ uint16 v_sync_width = mode.timing.v_sync_end - mode.timing.v_sync_start;
+ timing.v_sync_width = v_sync_width & 0xF;
+ timing.v_sync_width_high = (v_sync_width >> 4) & 0x3;
+
+ timing.h_size = 0;
+ timing.v_size = 0;
+ timing.h_size_high = 0;
+ timing.v_size_high = 0;
+ timing.h_border = 0;
+ timing.v_border = 0;
+ timing.interlaced = 0;
+ timing.stereo = 0;
+ timing.sync = 3;
+ timing.misc = 0;
+ timing.stereo_il = 0;
+
+ static const uint8 knownMode[] = { 0x64, 0x19, 0x00, 0x40, 0x41, 0x00,
0x26, 0x30, 0x18,
+ 0x88, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18};
+ // This is the EDID description for a standard 1024x768 timing.
We will find and replace
+ // all occurences of it in the BIOS with our custom mode.
+
+ // Get a pointer to the BIOS
+ const uintptr_t kBiosBase = 0xc0000;
+ const size_t kBiosSize = 0x10000;
+ uint8_t* bios = (uint8_t*)sBIOSModule->virtual_address(state,
kBiosBase);
+
+ int replacementCount = 0;
+ for(;;) {
+ bios = (uint8_t*)memmem(bios, kBiosSize, knownMode,
sizeof(knownMode));
+ if (bios == NULL)
+ break;
+ memcpy(bios, &timing, sizeof(timing));
+ bios = bios + 1;
+ replacementCount++;
+ }
+
+ dprintf(DEVICE_NAME ": patched custom mode in %d locations\n",
replacementCount);
+
+ // Did we manage to find a mode descriptor to replace?
+ if (replacementCount == 0)
+ return B_NOT_SUPPORTED;
+ return B_OK;
+}
+
+
+status_t
+vbe_patch_nvidia_bios(bios_state* state, display_mode& mode)
+{
+ struct nvidia_mode {
+ uint32 width;
+ uint32 height;
+ uint8 patch0[17];
+ uint8 patch1[9];
+ uint8 patch2[13];
+ uint8 patch3[5];
+ };
+
+ static const nvidia_mode allowedModes[] = {
+ {1280, 720, {0x16, 0xCB, 0x9F, 0x9F, 0x8F, 0xA7, 0x17, 0xEA,
0xD2, 0xCF, 0xCF, 0xEB, 0x47,
+ 0xE0, 0xC0, 0x00, 0x01},
+ {0x00, 0x05, 0xD0, 0x02, 0xA0, 0x2C, 0x10, 0x07, 0x05},
+ {0x7B, 0x01, 0x03, 0x7B, 0x01, 0x08, 0x01, 0x20, 0x80,
0x02, 0xFF, 0xFF, 0x20},
+ {0x00, 0x05, 0xBA, 0xD0, 0x02}},
+ {1280, 800, {0x12, 0xCD, 0x9F, 0x9F, 0x91, 0xA9, 0x1A, 0x3A,
0x21, 0x1F, 0x1F, 0x3B, 0x44,
+ 0xFE, 0xC0, 0x00, 0x01},
+ {0x00, 0x05, 0x20, 0x03, 0xA0, 0x32, 0x10, 0x23, 0x05},
+ {0x61, 0x01, 0x03, 0x61, 0x01, 0x08, 0x01, 0x20, 0x80,
0x02, 0xFF, 0xFF, 0x20},
+ {0x00, 0x05, 0xBA, 0x20, 0x03}},
+ {1360, 768, {0x16, 0xB9, 0xA9, 0x9F, 0x8F, 0xB2, 0x16, 0x14,
0x01, 0xFF, 0xCF, 0xEB, 0x46,
+ 0xEA, 0xC0, 0x00, 0x01},
+ {0x50, 0x05, 0x00, 0x03, 0xAA, 0x2F, 0x10, 0x07, 0x05},
+ {0x4D, 0x01, 0x03, 0x4D, 0x01, 0x08, 0x01, 0x20, 0xA8,
0x02, 0xFF, 0xFF, 0x20},
+ {0x50, 0x05, 0xBA, 0x00, 0x03}},
+ {1400, 1050, {0x12, 0xE6, 0xAE, 0xAE, 0x8A, 0xBB, 0x8E, 0x3D,
0x1B, 0x19, 0x19, 0x3E, 0x0E,
+ 0x00, 0xC0, 0x24, 0x12},
+ {0x78, 0x05, 0x1A, 0x04, 0xAF, 0x4A, 0x0E, 0x21, 0x05},
+ {0x49, 0x01, 0x03, 0x49, 0x01, 0x08, 0x01, 0x20, 0xBC,
0x02, 0xFF, 0xFF, 0x20},
+ {0x78, 0x05, 0xBA, 0x1A, 0x04}},
+ {1440, 900, {0x12, 0xE9, 0xB3, 0xB3, 0x8D, 0xBF, 0x92, 0xA3,
0x85, 0x83, 0x83, 0xA4, 0x48,
+ 0xFE, 0xC0, 0x00, 0x00},
+ {0xA0, 0x05, 0x84, 0x03, 0xB4, 0x38, 0x10, 0x24, 0x05},
+ {0x65, 0x01, 0x03, 0x65, 0x01, 0x08, 0x01, 0x20, 0xD0,
0x02, 0xFF, 0xFF, 0x20},
+ {0xA0, 0x05, 0xBA, 0x84, 0x03}},
+ {1600, 900, {0x1A, 0xD7, 0xC7, 0xC7, 0x9B, 0xCD, 0x11, 0x9C,
0x86, 0x83, 0x83, 0x9D, 0x4B,
+ 0xFE, 0xC0, 0x00, 0x00},
+ {0x40, 0x06, 0x84, 0x03, 0xC8, 0x38, 0x10, 0x27, 0x05},
+ {0x67, 0x01, 0x03, 0x67, 0x01, 0x08, 0x01, 0x20, 0x20,
0x03, 0xFF, 0xFF, 0x20},
+ {0x40, 0x06, 0xBA, 0x84, 0x03}},
+ {1600, 1200, {0x12, 0x03, 0xC7, 0xC7, 0x87, 0xD1, 0x09, 0xE0,
0xB1, 0xAF, 0xAF, 0xE1, 0x04,
+ 0x00, 0x01, 0x24, 0x13},
+ {0x40, 0x06, 0xB0, 0x04, 0xC8, 0x4A, 0x10, 0x19, 0x05},
+ {0x4A, 0x01, 0x03, 0x4A, 0x01, 0x08, 0x01, 0x20, 0x20,
0x03, 0xFF, 0xFF, 0x20},
+ {0x40, 0x06, 0xBA, 0xB0, 0x04}},
+ {1680, 1050, {0x12, 0x15, 0xD1, 0xD1, 0x99, 0xE0, 0x17, 0x3D,
0x1B, 0x19, 0x19, 0x3E, 0x0E,
+ 0x00, 0x01, 0x24, 0x13},
+ {0x90, 0x06, 0x1A, 0x04, 0xD2, 0x41, 0x10, 0x25, 0x05},
+ {0x69, 0x01, 0x03, 0x69, 0x01, 0x08, 0x01, 0x20, 0x48,
0x03, 0xFF, 0xFF, 0x20},
+ {0x90, 0x06, 0xBA, 0x1A, 0x04}},
+ {1920, 1080, {0x16, 0x0E, 0xEF, 0x9F, 0x8F, 0xFD, 0x02, 0x63,
0x3B, 0x37, 0xCF, 0xEB, 0x40,
+ 0x00, 0xC1, 0x24, 0x02},
+ {0x80, 0x07, 0x38, 0x04, 0xF0, 0x42, 0x10, 0x07, 0x05},
+ {0x4D, 0x01, 0x03, 0x4D, 0x01, 0x08, 0x01, 0x20, 0xC0,
0x03, 0xFF, 0xFF, 0x20},
+ {0x80, 0x07, 0xBA, 0x38, 0x04}},
+ {1920, 1200, {0x12, 0x3F, 0xEF, 0xEF, 0x83, 0x01, 0x1B, 0xD8,
0xB1, 0xAF, 0xAF, 0xD9, 0x04,
+ 0x00, 0x41, 0x25, 0x12},
+ {0x80, 0x07, 0xB0, 0x04, 0xF0, 0x4B, 0x10, 0x26, 0x05},
+ {0x7D, 0x01, 0x03, 0x7D, 0x01, 0x08, 0x01, 0x20, 0xC0,
0x03, 0xFF, 0xFF, 0x20},
+ {0x80, 0x07, 0xBA, 0xB0, 0x04}},
+ {2048, 1536, {0x12, 0x63, 0xFF, 0xFF, 0x9D, 0x12, 0x0E, 0x34,
0x01, 0x00, 0x00, 0x35, 0x44,
+ 0xE0, 0x41, 0x25, 0x13},
+ {0x00, 0x08, 0x00, 0x06, 0x00, 0x60, 0x10, 0x22, 0x05},
+ {0x7A, 0x01, 0x03, 0x52, 0x01, 0x08, 0x01, 0x20, 0x00,
0x04, 0xFF, 0xFF, 0x20},
+ {0x00, 0x08, 0xBA, 0x00, 0x06}}
+ };
+
+ static const nvidia_mode knownMode = { 0, 0,
+ {0x34, 0x2d, 0x27, 0x28, 0x90, 0x2b, 0xa0, 0xbf, 0x9c, 0x8f,
0x96, 0xb9, 0x8e, 0x1f, 0x00,
+ 0x00, 0x00},
+ {0x28, 0x00, 0x19, 0x00, 0x28, 0x18, 0x08, 0x08, 0x05},
+ {0x82, 0x0f, 0x03, 0x01, 0x00, 0x00, 0x08, 0x04, 0x14, 0x00,
0x00, 0x08, 0x17},
+ {0x40, 0x06, 0xba, 0xb0, 0x04}
+ };
+
+ size_t i;
+ for (i = 0; i < B_COUNT_OF(allowedModes); i++) {
+ if (allowedModes[i].width == mode.timing.h_display
+ && allowedModes[i].height == mode.timing.v_display) {
+ break;
+ }
+ }
+
+ if (i >= B_COUNT_OF(allowedModes))
+ return B_BAD_VALUE;
+
+ // Get a pointer to the BIOS
+ const uintptr_t kBiosBase = 0xc0000;
+ const size_t kBiosSize = 0x10000;
+ uint8_t* biosBase = (uint8_t*)sBIOSModule->virtual_address(state,
kBiosBase);
+
+ int replacementCount = 0;
+ uint8_t* bios = biosBase;
+ for(;;) {
+ bios = (uint8_t*)memmem(bios, kBiosSize, knownMode.patch0,
sizeof(knownMode.patch0));
+ if (bios == NULL)
+ break;
+ memcpy(bios, allowedModes[i].patch0,
sizeof(allowedModes[i].patch0));
+ bios = bios + 1;
+ replacementCount++;
+ }
+ dprintf(DEVICE_NAME ": applied patch0 in %d locations\n",
replacementCount);
+
+ replacementCount = 0;
+ bios = biosBase;
+ for(;;) {
+ bios = (uint8_t*)memmem(bios, kBiosSize, knownMode.patch1,
sizeof(knownMode.patch1));
+ if (bios == NULL)
+ break;
+ memcpy(bios, allowedModes[i].patch1,
sizeof(allowedModes[i].patch1));
+ bios = bios + 1;
+ replacementCount++;
+ }
+ dprintf(DEVICE_NAME ": applied patch1 in %d locations\n",
replacementCount);
+
+ replacementCount = 0;
+ bios = biosBase;
+ for(;;) {
+ bios = (uint8_t*)memmem(bios, kBiosSize, knownMode.patch2,
sizeof(knownMode.patch2));
+ if (bios == NULL)
+ break;
+ memcpy(bios, allowedModes[i].patch2,
sizeof(allowedModes[i].patch2));
+ bios = bios + 1;
+ replacementCount++;
+ }
+ dprintf(DEVICE_NAME ": applied patch1 in %d locations\n",
replacementCount);
+
+ replacementCount = 0;
+ bios = biosBase;
+ for(;;) {
+ bios = (uint8_t*)memmem(bios, kBiosSize, knownMode.patch3,
sizeof(knownMode.patch3));
+ if (bios == NULL)
+ break;
+ memcpy(bios, allowedModes[i].patch3,
sizeof(allowedModes[i].patch3));
+ bios = bios + 1;
+ replacementCount++;
+ }
+ dprintf(DEVICE_NAME ": applied patch1 in %d locations\n",
replacementCount);
+
+ if ((bios[0x34] & 0x8F) == 0x80)
+ bios[0x34] |= 0x01;
+
+ return B_OK;
+}
+
+
+status_t
+vbe_patch_atom1_bios(vesa_info& info, bios_state* state, display_mode& mode)
+{
+ // Get a pointer to the BIOS
+ const uintptr_t kBiosBase = 0xc0000;
+ uint8_t* bios = (uint8_t*)sBIOSModule->virtual_address(state,
kBiosBase);
+
+ ATOM_MODE_TIMING* timing = (ATOM_MODE_TIMING*)(bios +
info.shared_info->mode_table_offset);
+ dprintf(DEVICE_NAME ": patching ATOM mode timing (overwriting mode
%dx%d)\n",
+ timing->usCRTC_H_Disp, timing->usCRTC_V_Disp);
+
+ timing->usCRTC_H_Total = mode.timing.h_total;
+ timing->usCRTC_H_Disp = mode.timing.h_display;
+ timing->usCRTC_H_SyncStart = mode.timing.h_sync_start;
+ timing->usCRTC_H_SyncWidth = mode.timing.h_sync_end -
mode.timing.h_sync_start;
+
+ timing->usCRTC_V_Total = mode.timing.v_total;
+ timing->usCRTC_V_Disp = mode.timing.v_display;
+ timing->usCRTC_V_SyncStart = mode.timing.v_sync_start;
+ timing->usCRTC_V_SyncWidth = mode.timing.v_sync_end -
mode.timing.v_sync_start;
+
+ timing->usPixelClock = mode.timing.pixel_clock / 10;
+
+ return B_OK;
+}
+
+
+status_t
+vbe_patch_atom2_bios(vesa_info& info, bios_state* state, display_mode& mode)
+{
+ // Get a pointer to the BIOS
+ const uintptr_t kBiosBase = 0xc0000;
+ uint8_t* bios = (uint8_t*)sBIOSModule->virtual_address(state,
kBiosBase);
+
+ ATOM_DTD_FORMAT* timing = (ATOM_DTD_FORMAT*)(bios +
info.shared_info->mode_table_offset);
+ dprintf(DEVICE_NAME ": patching ATOM DTD format (overwriting mode
%dx%d)\n",
+ timing->usHActive, timing->usVActive);
+
+ timing->usHBlanking_Time = mode.timing.h_total - mode.timing.h_display;
+ timing->usHActive = mode.timing.h_display;
+ timing->usHSyncOffset = mode.timing.h_sync_start;
+ timing->usHSyncWidth = mode.timing.h_sync_end -
mode.timing.h_sync_start;
+
+ timing->usVBlanking_Time = mode.timing.v_total - mode.timing.v_display;
+ timing->usVActive = mode.timing.v_display;
+ timing->usVSyncOffset = mode.timing.v_sync_start;
+ timing->usVSyncWidth = mode.timing.v_sync_end -
mode.timing.v_sync_start;
+
+ timing->usPixClk = mode.timing.pixel_clock / 10;
+
+ return B_OK;
+}
+
+
+/*! Identify the BIOS type if it's one of the common ones, and locate where
the BIOS store its
+ * allowed video modes table. We can then patch this table to add extra video
modes that the
+ * manufacturer didn't allow.
+ */
+void
+vesa_identify_bios(bios_state* state, vesa_shared_info* sharedInfo)
+{
+ // Get a pointer to the BIOS
+ const uintptr_t kBiosBase = 0xc0000;
+ uint8_t* bios = (uint8_t*)sBIOSModule->virtual_address(state,
kBiosBase);
+
+ const size_t kAtomBiosHeaderOffset = 0x48;
+ const char kAtomSignature[] = {'A', 'T', 'O', 'M'};
+
+ ATOM_ROM_HEADER* atomRomHeader = (ATOM_ROM_HEADER*)(bios +
kAtomBiosHeaderOffset);
+
+ sharedInfo->bios_type = kUnknownBiosType;
+
+ if (*(uint16*)(bios + 0x44) == 0x8086) {
+ dprintf(DEVICE_NAME ": detected Intel BIOS\n");
+
+ // TODO check if we can find the mode table
+ sharedInfo->bios_type = kIntelBiosType;
+ } else if (memcmp(atomRomHeader->uaFirmWareSignature, kAtomSignature,
4) == 0) {
+ dprintf(DEVICE_NAME ": detected ATOM BIOS\n");
+
+ ATOM_MASTER_DATA_TABLE* masterDataTable =
(ATOM_MASTER_DATA_TABLE*)(bios
+ + atomRomHeader->usMasterDataTableOffset);
+ dprintf(DEVICE_NAME ": list of data tables: %p",
&masterDataTable->ListOfDataTables);
+ ATOM_ANALOG_TV_INFO* standardVesaTable =
(ATOM_ANALOG_TV_INFO*)(bios
+ +
masterDataTable->ListOfDataTables.StandardVESA_Timing);
+ dprintf(DEVICE_NAME ": std_vesa: %p", standardVesaTable);
+ sharedInfo->mode_table_offset =
(uint8*)&standardVesaTable->aModeTimings - bios;
+
+ size_t tableSize = standardVesaTable->sHeader.usStructureSize
+ - sizeof(ATOM_COMMON_TABLE_HEADER);
+ if (tableSize % sizeof(ATOM_MODE_TIMING) == 0)
+ sharedInfo->bios_type = kAtomBiosType2;
+ else
+ sharedInfo->bios_type = kAtomBiosType1;
+ } else if (memmem(bios, 512, "NVID", 4) != NULL) {
+ dprintf(DEVICE_NAME ": detected nVidia BIOS\n");
+
+ // TODO check if we can find the mode table
+ sharedInfo->bios_type = kNVidiaBiosType;
+ } else {
+ dprintf(DEVICE_NAME ": unknown BIOS type, custom video modes
will not be available\n");
+ }
+}
+
+
+/*! Set a custom display mode by live patching the VESA BIOS to insert it in
the modeline table.
+ *
+ * This is only supported for some video cards, where the format of the mode
lines is known.
+ */
+status_t
+vesa_set_custom_display_mode(vesa_info& info, display_mode& mode)
+{
+ int32 modeIndex = -1;
+ if (info.shared_info->bios_type == kUnknownBiosType)
+ return B_NOT_SUPPORTED;
+
+ // Prepare BIOS environment
+ bios_state* state;
+ status_t status = vbe_call_prepare(&state);
+ if (status != B_OK)
+ return status;
+
+ // Patch bios to inject custom video mode
+ switch (info.shared_info->bios_type) {
+ case kIntelBiosType:
+ status = vbe_patch_intel_bios(state, mode);
+ // The patch replaces the 1024x768 modes with our
custom resolution. We can then use
+ // mode 0x118 which is the standard VBE2 mode for
1024x768 at 32 bits per pixel, and
+ // know it will use our new timings.
+ break;
+ case kNVidiaBiosType:
+ status = vbe_patch_nvidia_bios(state, mode);
+ break;
+ case kAtomBiosType1:
+ status = vbe_patch_atom1_bios(info, state, mode);
+ break;
+ case kAtomBiosType2:
+ status = vbe_patch_atom2_bios(info, state, mode);
+ break;
+ default:
+ status = B_NOT_SUPPORTED;
+ break;
+ }
+
+ if (status != B_OK)
+ goto out;
+
+ // The patching modified some mode, but we don't know which one. So we
need to rescan the mode
+ // list to find the correct one.
+ struct vbe_mode_info modeInfo;
+ for (uint32 i = 0; i < info.shared_info->mode_count; i++) {
+ status = vbe_get_mode_info(state, info.modes[i].mode,
&modeInfo);
+ if (status != B_OK) {
+ // Sometimes the patching prevents us from getting the
mode info?
+ dprintf(DEVICE_NAME ": vesa_set_custom_display_mode():
cannot get mode info for %x\n",
+ info.modes[i].mode);
+ // Just ignore modes that turn out to be invalid...
+ continue;
+ }
+
+ if (modeInfo.width == mode.timing.h_display && modeInfo.height
== mode.timing.v_display
+ &&
get_color_space_for_depth(info.modes[i].bits_per_pixel) == mode.space) {
+ modeIndex = info.modes[i].mode;
+ break;
+ }
+ }
+
+ if (modeIndex >= 0) {
+ dprintf(DEVICE_NAME ": custom mode resolution %dx%d succesfully
patched at index %x\n",
+ modeInfo.width, modeInfo.height, modeIndex);
+ } else {
+ dprintf(DEVICE_NAME ": video mode patching failed!\n");
+ goto out;
+ }
+
+ // Set mode
+ status = vbe_set_mode(state, modeIndex);
+ if (status != B_OK) {
+ dprintf(DEVICE_NAME ": vesa_set_custom_display_mode(): cannot
set mode\n");
+ goto out;
+ }
+
+ if (info.modes[modeIndex].bits_per_pixel <= 8)
+ vbe_set_bits_per_gun(state, info, 8);
+
+ // Map new frame buffer if necessary
+
+ status = remap_frame_buffer(info, modeInfo.physical_base,
modeInfo.width,
+ modeInfo.height, modeInfo.bits_per_pixel,
modeInfo.bytes_per_row,
+ false);
+
+ if (status == B_OK) {
+ // Update shared frame buffer information
+ info.shared_info->current_mode.virtual_width = modeInfo.width;
+ info.shared_info->current_mode.virtual_height = modeInfo.height;
+ info.shared_info->current_mode.space =
get_color_space_for_depth(
+ modeInfo.bits_per_pixel);
+ }
+
+out:
+ vbe_call_finish(state);
+ return status;
+}
+
+
diff --git a/src/add-ons/kernel/drivers/graphics/vesa/vesa.cpp
b/src/add-ons/kernel/drivers/graphics/vesa/vesa.cpp
index 2f0c815..05ccb40 100644
--- a/src/add-ons/kernel/drivers/graphics/vesa/vesa.cpp
+++ b/src/add-ons/kernel/drivers/graphics/vesa/vesa.cpp
@@ -7,11 +7,6 @@
#include "vesa_private.h"
#include "vesa.h"
-#define _GNU_SOURCE
-#include <string.h>
-
-#include <drivers/bios.h>
-
#include <boot_item.h>
#include <frame_buffer_console.h>
#include <util/kernel_cpp.h>
@@ -21,8 +16,6 @@
#include "utility.h"
#include "vesa_info.h"
-#include "atombios.h"
-
#define LINEAR_ADDRESS(segment, offset) \
(((addr_t)(segment) << 4) + (addr_t)(offset))
@@ -30,13 +23,13 @@
LINEAR_ADDRESS((addr_t)(segmented) >> 16, (addr_t)(segmented) &
0xffff)
-static bios_module_info* sBIOSModule;
+bios_module_info* sBIOSModule;
/*! Loads the BIOS module and sets up a state for it. The BIOS module is
only
loaded when we need it, as it is quite a large module.
*/
-static status_t
+status_t
vbe_call_prepare(bios_state** state)
{
status_t status;
@@ -59,7 +52,7 @@
}
-static void
+void
vbe_call_finish(bios_state* state)
{
sBIOSModule->finish(state);
@@ -101,7 +94,7 @@
}
-static uint32
+uint32
get_color_space_for_depth(uint32 depth)
{
switch (depth) {
@@ -126,7 +119,7 @@
}
-static status_t
+status_t
vbe_get_mode_info(bios_state* state, uint16 mode, struct vbe_mode_info*
modeInfo)
{
void* vbeModeInfo = sBIOSModule->allocate_mem(state,
@@ -160,7 +153,7 @@
}
-static status_t
+status_t
vbe_set_mode(bios_state* state, uint16 mode)
{
bios_regs regs = {};
@@ -231,7 +224,7 @@
}
-static status_t
+status_t
vbe_set_bits_per_gun(bios_state* state, vesa_info& info, uint8 bits)
{
info.bits_per_gun = 6;
@@ -290,61 +283,10 @@
}
-/*! Identify the BIOS type if it's one of the common ones, and locate where
the BIOS store its
- * allowed video modes table. We can then patch this table to add extra video
modes that the
- * manufacturer didn't allow.
- */
-static void
-vbe_identify_bios(bios_state* state, vesa_shared_info* sharedInfo)
-{
- // Get a pointer to the BIOS
- const uintptr_t kBiosBase = 0xc0000;
- uint8_t* bios = (uint8_t*)sBIOSModule->virtual_address(state,
kBiosBase);
-
- const size_t kAtomBiosHeaderOffset = 0x48;
- const char kAtomSignature[] = {'A', 'T', 'O', 'M'};
-
- ATOM_ROM_HEADER* atomRomHeader = (ATOM_ROM_HEADER*)(bios +
kAtomBiosHeaderOffset);
-
- sharedInfo->bios_type = kUnknownBiosType;
-
- if (*(uint16*)(bios + 0x44) == 0x8086) {
- dprintf(DEVICE_NAME ": detected Intel BIOS\n");
-
- // TODO check if we can find the mode table
- sharedInfo->bios_type = kIntelBiosType;
- } else if (memcmp(atomRomHeader->uaFirmWareSignature, kAtomSignature,
4) == 0) {
- dprintf(DEVICE_NAME ": detected ATOM BIOS\n");
-
- ATOM_MASTER_DATA_TABLE* masterDataTable =
(ATOM_MASTER_DATA_TABLE*)(bios
- + atomRomHeader->usMasterDataTableOffset);
- dprintf(DEVICE_NAME ": list of data tables: %p",
&masterDataTable->ListOfDataTables);
- ATOM_ANALOG_TV_INFO* standardVesaTable =
(ATOM_ANALOG_TV_INFO*)(bios
- +
masterDataTable->ListOfDataTables.StandardVESA_Timing);
- dprintf(DEVICE_NAME ": std_vesa: %p", standardVesaTable);
- sharedInfo->mode_table_offset =
(uint8*)&standardVesaTable->aModeTimings - bios;
-
- size_t tableSize = standardVesaTable->sHeader.usStructureSize
- - sizeof(ATOM_COMMON_TABLE_HEADER);
- if (tableSize % sizeof(ATOM_MODE_TIMING) == 0)
- sharedInfo->bios_type = kAtomBiosType2;
- else
- sharedInfo->bios_type = kAtomBiosType1;
- } else if (memmem(bios, 512, "NVID", 4) != NULL) {
- dprintf(DEVICE_NAME ": detected nVidia BIOS\n");
-
- // TODO check if we can find the mode table
- sharedInfo->bios_type = kNVidiaBiosType;
- } else {
- dprintf(DEVICE_NAME ": unknown BIOS type, custom video modes
will not be available\n");
- }
-}
-
-
/*! Remaps the frame buffer if necessary; if we've already mapped the
complete
frame buffer, there is no need to map it again.
*/
-static status_t
+status_t
remap_frame_buffer(vesa_info& info, addr_t physicalBase, uint32 width,
uint32 height, int8 depth, uint32 bytesPerRow, bool initializing)
{
@@ -472,7 +414,7 @@
if (status != B_OK)
return status;
- vbe_identify_bios(state, &sharedInfo);
+ vesa_identify_bios(state, &sharedInfo);
vbe_get_dpms_capabilities(state, info.vbe_dpms_capabilities,
sharedInfo.dpms_capabilities);
@@ -546,383 +488,6 @@
status_t
-vbe_patch_intel_bios(bios_state* state, display_mode& mode)
-{
- edid1_detailed_timing_raw timing;
-
- timing.pixel_clock = mode.timing.pixel_clock / 10;
-
- timing.h_active = mode.timing.h_display & 0xFF;
- timing.h_active_high = (mode.timing.h_display >> 8) & 0xF;
-
- uint16 h_blank = mode.timing.h_total - mode.timing.h_display;
- timing.h_blank = h_blank & 0xff;
- timing.h_blank_high = (h_blank >> 8) & 0xF;
-
- timing.v_active = mode.timing.v_display & 0xFF;
- timing.v_active_high = (mode.timing.v_display >> 8) & 0xF;
-
- uint16 v_blank = mode.timing.v_total - mode.timing.v_display;
- timing.v_blank = v_blank & 0xff;
- timing.v_blank_high = (v_blank >> 8) & 0xF;
-
- uint16 h_sync_off = mode.timing.h_sync_start - mode.timing.h_display;
- timing.h_sync_off = h_sync_off & 0xFF;
- timing.h_sync_off_high = (h_sync_off >> 8) & 0x3;
-
- uint16 h_sync_width = mode.timing.h_sync_end - mode.timing.h_sync_start;
- timing.h_sync_width = h_sync_width & 0xFF;
- timing.h_sync_width_high = (h_sync_width >> 8) & 0x3;
-
- uint16 v_sync_off = mode.timing.v_sync_start - mode.timing.v_display;
- timing.v_sync_off = v_sync_off & 0xF;
- timing.v_sync_off_high = (v_sync_off >> 4) & 0x3;
-
- uint16 v_sync_width = mode.timing.v_sync_end - mode.timing.v_sync_start;
- timing.v_sync_width = v_sync_width & 0xF;
- timing.v_sync_width_high = (v_sync_width >> 4) & 0x3;
-
- timing.h_size = 0;
- timing.v_size = 0;
- timing.h_size_high = 0;
- timing.v_size_high = 0;
- timing.h_border = 0;
- timing.v_border = 0;
- timing.interlaced = 0;
- timing.stereo = 0;
- timing.sync = 3;
- timing.misc = 0;
- timing.stereo_il = 0;
-
- static const uint8 knownMode[] = { 0x64, 0x19, 0x00, 0x40, 0x41, 0x00,
0x26, 0x30, 0x18,
- 0x88, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18};
- // This is the EDID description for a standard 1024x768 timing.
We will find and replace
- // all occurences of it in the BIOS with our custom mode.
-
- // Get a pointer to the BIOS
- const uintptr_t kBiosBase = 0xc0000;
- const size_t kBiosSize = 0x10000;
- uint8_t* bios = (uint8_t*)sBIOSModule->virtual_address(state,
kBiosBase);
-
- int replacementCount = 0;
- for(;;) {
- bios = (uint8_t*)memmem(bios, kBiosSize, knownMode,
sizeof(knownMode));
- if (bios == NULL)
- break;
- memcpy(bios, &timing, sizeof(timing));
- bios = bios + 1;
- replacementCount++;
- }
-
- dprintf(DEVICE_NAME ": patched custom mode in %d locations\n",
replacementCount);
-
- // Did we manage to find a mode descriptor to replace?
- if (replacementCount == 0)
- return B_NOT_SUPPORTED;
- return B_OK;
-}
-
-
-status_t
-vbe_patch_nvidia_bios(bios_state* state, display_mode& mode)
-{
- struct nvidia_mode {
- uint32 width;
- uint32 height;
- uint8 patch0[17];
- uint8 patch1[9];
- uint8 patch2[13];
- uint8 patch3[5];
- };
-
- static const nvidia_mode allowedModes[] = {
- {1280, 720, {0x16, 0xCB, 0x9F, 0x9F, 0x8F, 0xA7, 0x17, 0xEA,
0xD2, 0xCF, 0xCF, 0xEB, 0x47,
- 0xE0, 0xC0, 0x00, 0x01},
- {0x00, 0x05, 0xD0, 0x02, 0xA0, 0x2C, 0x10, 0x07, 0x05},
- {0x7B, 0x01, 0x03, 0x7B, 0x01, 0x08, 0x01, 0x20, 0x80,
0x02, 0xFF, 0xFF, 0x20},
- {0x00, 0x05, 0xBA, 0xD0, 0x02}},
- {1280, 800, {0x12, 0xCD, 0x9F, 0x9F, 0x91, 0xA9, 0x1A, 0x3A,
0x21, 0x1F, 0x1F, 0x3B, 0x44,
- 0xFE, 0xC0, 0x00, 0x01},
- {0x00, 0x05, 0x20, 0x03, 0xA0, 0x32, 0x10, 0x23, 0x05},
- {0x61, 0x01, 0x03, 0x61, 0x01, 0x08, 0x01, 0x20, 0x80,
0x02, 0xFF, 0xFF, 0x20},
- {0x00, 0x05, 0xBA, 0x20, 0x03}},
- {1360, 768, {0x16, 0xB9, 0xA9, 0x9F, 0x8F, 0xB2, 0x16, 0x14,
0x01, 0xFF, 0xCF, 0xEB, 0x46,
- 0xEA, 0xC0, 0x00, 0x01},
- {0x50, 0x05, 0x00, 0x03, 0xAA, 0x2F, 0x10, 0x07, 0x05},
- {0x4D, 0x01, 0x03, 0x4D, 0x01, 0x08, 0x01, 0x20, 0xA8,
0x02, 0xFF, 0xFF, 0x20},
- {0x50, 0x05, 0xBA, 0x00, 0x03}},
- {1400, 1050, {0x12, 0xE6, 0xAE, 0xAE, 0x8A, 0xBB, 0x8E, 0x3D,
0x1B, 0x19, 0x19, 0x3E, 0x0E,
- 0x00, 0xC0, 0x24, 0x12},
- {0x78, 0x05, 0x1A, 0x04, 0xAF, 0x4A, 0x0E, 0x21, 0x05},
- {0x49, 0x01, 0x03, 0x49, 0x01, 0x08, 0x01, 0x20, 0xBC,
0x02, 0xFF, 0xFF, 0x20},
- {0x78, 0x05, 0xBA, 0x1A, 0x04}},
- {1440, 900, {0x12, 0xE9, 0xB3, 0xB3, 0x8D, 0xBF, 0x92, 0xA3,
0x85, 0x83, 0x83, 0xA4, 0x48,
- 0xFE, 0xC0, 0x00, 0x00},
- {0xA0, 0x05, 0x84, 0x03, 0xB4, 0x38, 0x10, 0x24, 0x05},
- {0x65, 0x01, 0x03, 0x65, 0x01, 0x08, 0x01, 0x20, 0xD0,
0x02, 0xFF, 0xFF, 0x20},
- {0xA0, 0x05, 0xBA, 0x84, 0x03}},
- {1600, 900, {0x1A, 0xD7, 0xC7, 0xC7, 0x9B, 0xCD, 0x11, 0x9C,
0x86, 0x83, 0x83, 0x9D, 0x4B,
- 0xFE, 0xC0, 0x00, 0x00},
- {0x40, 0x06, 0x84, 0x03, 0xC8, 0x38, 0x10, 0x27, 0x05},
- {0x67, 0x01, 0x03, 0x67, 0x01, 0x08, 0x01, 0x20, 0x20,
0x03, 0xFF, 0xFF, 0x20},
- {0x40, 0x06, 0xBA, 0x84, 0x03}},
- {1600, 1200, {0x12, 0x03, 0xC7, 0xC7, 0x87, 0xD1, 0x09, 0xE0,
0xB1, 0xAF, 0xAF, 0xE1, 0x04,
- 0x00, 0x01, 0x24, 0x13},
- {0x40, 0x06, 0xB0, 0x04, 0xC8, 0x4A, 0x10, 0x19, 0x05},
- {0x4A, 0x01, 0x03, 0x4A, 0x01, 0x08, 0x01, 0x20, 0x20,
0x03, 0xFF, 0xFF, 0x20},
- {0x40, 0x06, 0xBA, 0xB0, 0x04}},
- {1680, 1050, {0x12, 0x15, 0xD1, 0xD1, 0x99, 0xE0, 0x17, 0x3D,
0x1B, 0x19, 0x19, 0x3E, 0x0E,
- 0x00, 0x01, 0x24, 0x13},
- {0x90, 0x06, 0x1A, 0x04, 0xD2, 0x41, 0x10, 0x25, 0x05},
- {0x69, 0x01, 0x03, 0x69, 0x01, 0x08, 0x01, 0x20, 0x48,
0x03, 0xFF, 0xFF, 0x20},
- {0x90, 0x06, 0xBA, 0x1A, 0x04}},
- {1920, 1080, {0x16, 0x0E, 0xEF, 0x9F, 0x8F, 0xFD, 0x02, 0x63,
0x3B, 0x37, 0xCF, 0xEB, 0x40,
- 0x00, 0xC1, 0x24, 0x02},
- {0x80, 0x07, 0x38, 0x04, 0xF0, 0x42, 0x10, 0x07, 0x05},
- {0x4D, 0x01, 0x03, 0x4D, 0x01, 0x08, 0x01, 0x20, 0xC0,
0x03, 0xFF, 0xFF, 0x20},
- {0x80, 0x07, 0xBA, 0x38, 0x04}},
- {1920, 1200, {0x12, 0x3F, 0xEF, 0xEF, 0x83, 0x01, 0x1B, 0xD8,
0xB1, 0xAF, 0xAF, 0xD9, 0x04,
- 0x00, 0x41, 0x25, 0x12},
- {0x80, 0x07, 0xB0, 0x04, 0xF0, 0x4B, 0x10, 0x26, 0x05},
- {0x7D, 0x01, 0x03, 0x7D, 0x01, 0x08, 0x01, 0x20, 0xC0,
0x03, 0xFF, 0xFF, 0x20},
- {0x80, 0x07, 0xBA, 0xB0, 0x04}},
- {2048, 1536, {0x12, 0x63, 0xFF, 0xFF, 0x9D, 0x12, 0x0E, 0x34,
0x01, 0x00, 0x00, 0x35, 0x44,
- 0xE0, 0x41, 0x25, 0x13},
- {0x00, 0x08, 0x00, 0x06, 0x00, 0x60, 0x10, 0x22, 0x05},
- {0x7A, 0x01, 0x03, 0x52, 0x01, 0x08, 0x01, 0x20, 0x00,
0x04, 0xFF, 0xFF, 0x20},
- {0x00, 0x08, 0xBA, 0x00, 0x06}}
- };
-
- static const nvidia_mode knownMode = { 0, 0,
- {0x34, 0x2d, 0x27, 0x28, 0x90, 0x2b, 0xa0, 0xbf, 0x9c, 0x8f,
0x96, 0xb9, 0x8e, 0x1f, 0x00,
- 0x00, 0x00},
- {0x28, 0x00, 0x19, 0x00, 0x28, 0x18, 0x08, 0x08, 0x05},
- {0x82, 0x0f, 0x03, 0x01, 0x00, 0x00, 0x08, 0x04, 0x14, 0x00,
0x00, 0x08, 0x17},
- {0x40, 0x06, 0xba, 0xb0, 0x04}
- };
-
- int i;
- for (i = 0; i < B_COUNT_OF(allowedModes); i++) {
- if (allowedModes[i].width == mode.timing.h_display
- && allowedModes[i].height == mode.timing.v_display) {
- break;
- }
- }
-
- if (i >= B_COUNT_OF(allowedModes))
- return B_BAD_VALUE;
-
- // Get a pointer to the BIOS
- const uintptr_t kBiosBase = 0xc0000;
- const size_t kBiosSize = 0x10000;
- uint8_t* biosBase = (uint8_t*)sBIOSModule->virtual_address(state,
kBiosBase);
-
- int replacementCount = 0;
- uint8_t* bios = biosBase;
- for(;;) {
- bios = (uint8_t*)memmem(bios, kBiosSize, knownMode.patch0,
sizeof(knownMode.patch0));
- if (bios == NULL)
- break;
- memcpy(bios, allowedModes[i].patch0,
sizeof(allowedModes[i].patch0));
- bios = bios + 1;
- replacementCount++;
- }
- dprintf(DEVICE_NAME ": applied patch0 in %d locations\n",
replacementCount);
-
- replacementCount = 0;
- bios = biosBase;
- for(;;) {
- bios = (uint8_t*)memmem(bios, kBiosSize, knownMode.patch1,
sizeof(knownMode.patch1));
- if (bios == NULL)
- break;
- memcpy(bios, allowedModes[i].patch1,
sizeof(allowedModes[i].patch1));
- bios = bios + 1;
- replacementCount++;
- }
- dprintf(DEVICE_NAME ": applied patch1 in %d locations\n",
replacementCount);
-
- replacementCount = 0;
- bios = biosBase;
- for(;;) {
- bios = (uint8_t*)memmem(bios, kBiosSize, knownMode.patch2,
sizeof(knownMode.patch2));
- if (bios == NULL)
- break;
- memcpy(bios, allowedModes[i].patch2,
sizeof(allowedModes[i].patch2));
- bios = bios + 1;
- replacementCount++;
- }
- dprintf(DEVICE_NAME ": applied patch1 in %d locations\n",
replacementCount);
-
- replacementCount = 0;
- bios = biosBase;
- for(;;) {
- bios = (uint8_t*)memmem(bios, kBiosSize, knownMode.patch3,
sizeof(knownMode.patch3));
- if (bios == NULL)
- break;
- memcpy(bios, allowedModes[i].patch3,
sizeof(allowedModes[i].patch3));
- bios = bios + 1;
- replacementCount++;
- }
- dprintf(DEVICE_NAME ": applied patch1 in %d locations\n",
replacementCount);
-
- if ((bios[0x34] & 0x8F) == 0x80)
- bios[0x34] |= 0x01;
-
- return B_OK;
-}
-
-
-status_t
-vbe_patch_atom1_bios(vesa_info& info, bios_state* state, display_mode& mode)
-{
- // Get a pointer to the BIOS
- const uintptr_t kBiosBase = 0xc0000;
- uint8_t* bios = (uint8_t*)sBIOSModule->virtual_address(state,
kBiosBase);
-
- ATOM_MODE_TIMING* timing = (ATOM_MODE_TIMING*)(bios +
info.shared_info->mode_table_offset);
- dprintf(DEVICE_NAME ": patching ATOM mode timing (overwriting mode
%dx%d)\n",
- timing->usCRTC_H_Disp, timing->usCRTC_V_Disp);
-
- timing->usCRTC_H_Total = mode.timing.h_total;
- timing->usCRTC_H_Disp = mode.timing.h_display;
- timing->usCRTC_H_SyncStart = mode.timing.h_sync_start;
- timing->usCRTC_H_SyncWidth = mode.timing.h_sync_end -
mode.timing.h_sync_start;
-
- timing->usCRTC_V_Total = mode.timing.v_total;
- timing->usCRTC_V_Disp = mode.timing.v_display;
- timing->usCRTC_V_SyncStart = mode.timing.v_sync_start;
- timing->usCRTC_V_SyncWidth = mode.timing.v_sync_end -
mode.timing.v_sync_start;
-
- timing->usPixelClock = mode.timing.pixel_clock / 10;
-
- return B_OK;
-}
-
-
-status_t
-vbe_patch_atom2_bios(vesa_info& info, bios_state* state, display_mode& mode)
-{
- // Get a pointer to the BIOS
- const uintptr_t kBiosBase = 0xc0000;
- uint8_t* bios = (uint8_t*)sBIOSModule->virtual_address(state,
kBiosBase);
-
- ATOM_DTD_FORMAT* timing = (ATOM_DTD_FORMAT*)(bios +
info.shared_info->mode_table_offset);
- dprintf(DEVICE_NAME ": patching ATOM DTD format (overwriting mode
%dx%d)\n",
- timing->usHActive, timing->usVActive);
-
- timing->usHBlanking_Time = mode.timing.h_total - mode.timing.h_display;
- timing->usHActive = mode.timing.h_display;
- timing->usHSyncOffset = mode.timing.h_sync_start;
- timing->usHSyncWidth = mode.timing.h_sync_end -
mode.timing.h_sync_start;
-
- timing->usVBlanking_Time = mode.timing.v_total - mode.timing.v_display;
- timing->usVActive = mode.timing.v_display;
- timing->usVSyncOffset = mode.timing.v_sync_start;
- timing->usVSyncWidth = mode.timing.v_sync_end -
mode.timing.v_sync_start;
-
- timing->usPixClk = mode.timing.pixel_clock / 10;
-
- return B_OK;
-}
-
-
-status_t
-vesa_set_custom_display_mode(vesa_info& info, display_mode& mode)
-{
- int32 modeIndex = -1;
- if (info.shared_info->bios_type == kUnknownBiosType)
- return B_NOT_SUPPORTED;
-
- // Prepare BIOS environment
- bios_state* state;
- status_t status = vbe_call_prepare(&state);
- if (status != B_OK)
- return status;
-
- // Patch bios to inject custom video mode
- switch (info.shared_info->bios_type) {
- case kIntelBiosType:
- status = vbe_patch_intel_bios(state, mode);
- // The patch replaces the 1024x768 modes with our
custom resolution. We can then use
- // mode 0x118 which is the standard VBE2 mode for
1024x768 at 32 bits per pixel, and
- // know it will use our new timings.
- break;
- case kNVidiaBiosType:
- status = vbe_patch_nvidia_bios(state, mode);
- break;
- case kAtomBiosType1:
- status = vbe_patch_atom1_bios(info, state, mode);
- break;
- case kAtomBiosType2:
- status = vbe_patch_atom2_bios(info, state, mode);
- break;
- default:
- status = B_NOT_SUPPORTED;
- break;
- }
-
- if (status != B_OK)
- goto out;
-
- // The patching modified some mode, but we don't know which one. So we
need to rescan the mode
- // list to find the correct one.
- struct vbe_mode_info modeInfo;
- for (int i = 0; i < info.shared_info->mode_count; i++) {
- status = vbe_get_mode_info(state, info.modes[i].mode,
&modeInfo);
- if (status != B_OK) {
- // Sometimes the patching prevents us from getting the
mode info?
- dprintf(DEVICE_NAME ": vesa_set_custom_display_mode():
cannot get mode info for %x\n",
- info.modes[i].mode);
- // Just ignore modes that turn out to be invalid...
- continue;
- }
-
- if (modeInfo.width == mode.timing.h_display && modeInfo.height
== mode.timing.v_display
- &&
get_color_space_for_depth(info.modes[i].bits_per_pixel) == mode.space) {
- modeIndex = info.modes[i].mode;
- break;
- }
- }
-
- if (modeIndex >= 0) {
- dprintf(DEVICE_NAME ": custom mode resolution %dx%d succesfully
patched at index %x\n",
- modeInfo.width, modeInfo.height, modeIndex);
- } else {
- dprintf(DEVICE_NAME ": video mode patching failed!\n");
- goto out;
- }
-
- // Set mode
- status = vbe_set_mode(state, modeIndex);
- if (status != B_OK) {
- dprintf(DEVICE_NAME ": vesa_set_custom_display_mode(): cannot
set mode\n");
- goto out;
- }
-
- if (info.modes[modeIndex].bits_per_pixel <= 8)
- vbe_set_bits_per_gun(state, info, 8);
-
- // Map new frame buffer if necessary
-
- status = remap_frame_buffer(info, modeInfo.physical_base,
modeInfo.width,
- modeInfo.height, modeInfo.bits_per_pixel,
modeInfo.bytes_per_row,
- false);
-
- if (status == B_OK) {
- // Update shared frame buffer information
- info.shared_info->current_mode.virtual_width = modeInfo.width;
- info.shared_info->current_mode.virtual_height = modeInfo.height;
- info.shared_info->current_mode.space =
get_color_space_for_depth(
- modeInfo.bits_per_pixel);
- }
-
-out:
- vbe_call_finish(state);
- return status;
-}
-
-
-status_t
vesa_get_dpms_mode(vesa_info& info, uint32& mode)
{
mode = B_DPMS_ON;
diff --git a/src/add-ons/kernel/drivers/graphics/vesa/vesa_private.h
b/src/add-ons/kernel/drivers/graphics/vesa/vesa_private.h
index 05458d1..c4d0352 100644
--- a/src/add-ons/kernel/drivers/graphics/vesa/vesa_private.h
+++ b/src/add-ons/kernel/drivers/graphics/vesa/vesa_private.h
@@ -10,6 +10,8 @@
#include <Accelerant.h>
#include <PCI.h>
+#include <drivers/bios.h>
+
#define DEVICE_NAME "vesa"
#define VESA_ACCELERANT_NAME "vesa.accelerant"
@@ -42,7 +44,8 @@
extern status_t vesa_set_custom_display_mode(vesa_info& info, display_mode&
mode);
extern status_t vesa_get_dpms_mode(vesa_info& info, uint32& mode);
extern status_t vesa_set_dpms_mode(vesa_info& info, uint32 mode);
-extern status_t vesa_set_indexed_colors(vesa_info& info, uint8 first,
- uint8* colors, uint16 count);
+extern status_t vesa_set_indexed_colors(vesa_info& info, uint8 first, uint8*
colors, uint16 count);
+
+extern void vesa_identify_bios(bios_state* state, vesa_shared_info*
sharedInfo);
#endif /* VESA_PRIVATE_H */
--
To view, visit https://review.haiku-os.org/c/haiku/+/4650
To unsubscribe, or for help writing mail filters, visit
https://review.haiku-os.org/settings
Gerrit-Project: haiku
Gerrit-Branch: master
Gerrit-Change-Id: I453ae4c8ee198a31b5550a31d7ae37bec2cc382f
Gerrit-Change-Number: 4650
Gerrit-PatchSet: 1
Gerrit-Owner: Adrien Destugues <pulkomandy@xxxxxxxxx>
Gerrit-MessageType: newchange