From 6a175a5ddcf15f0da49a94d0c9efa8676b5a70d5 Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Fri, 29 Oct 2021 11:09:05 +0200 Subject: [PATCH] vesa: report BIOS manufacturer (visible in screen preferences) Get the OEM string from the VESA info block (and also get the memory size from there while we are at it). If the string is empty, use the BIOS type (identified in other ways) to still report something. Change-Id: I8cbd75d19f624a43db05e82d1e1b2a536cc418b6 Reviewed-on: https://review.haiku-os.org/c/haiku/+/4625 Tested-by: Commit checker robot Reviewed-by: waddlesplash --- headers/private/graphics/vesa/vesa_info.h | 3 + src/add-ons/accelerants/vesa/accelerant.cpp | 26 ++++++- .../kernel/drivers/graphics/vesa/vesa.cpp | 77 +++++++++++-------- 3 files changed, 68 insertions(+), 38 deletions(-) diff --git a/headers/private/graphics/vesa/vesa_info.h b/headers/private/graphics/vesa/vesa_info.h index 4d3c060833..77d4fe6379 100644 --- a/headers/private/graphics/vesa/vesa_info.h +++ b/headers/private/graphics/vesa/vesa_info.h @@ -52,6 +52,9 @@ struct vesa_shared_info { // Atombios only: offset to the table of video modes in the bios, used for patching in // extra video modes. uint32 dpms_capabilities; + + char name[32]; + uint32 vram_size; }; //----------------- ioctl() interface ---------------- diff --git a/src/add-ons/accelerants/vesa/accelerant.cpp b/src/add-ons/accelerants/vesa/accelerant.cpp index 4daeea8749..93b225fae1 100644 --- a/src/add-ons/accelerants/vesa/accelerant.cpp +++ b/src/add-ons/accelerants/vesa/accelerant.cpp @@ -184,13 +184,31 @@ status_t vesa_get_accelerant_device_info(accelerant_device_info *info) { info->version = B_ACCELERANT_VERSION; - strcpy(info->name, "VESA Driver"); - strcpy(info->chipset, "VESA"); - // ToDo: provide some more insight here... + + strcpy(info->name, "VESA driver"); + if (gInfo->shared_info->name[0] != '\0') { + strlcpy(info->chipset, gInfo->shared_info->name, 32); + } else { + switch (gInfo->shared_info->bios_type) { + case kIntelBiosType: + strcpy(info->chipset, "Intel"); + break; + case kNVidiaBiosType: + strcpy(info->chipset, "nVidia"); + break; + case kAtomBiosType1: + case kAtomBiosType2: + strcpy(info->chipset, "AMD/ATI Atombios"); + break; + default: + strcpy(info->chipset, "Generic VESA"); + break; + } + } strcpy(info->serial_no, "None"); + info->memory = gInfo->shared_info->vram_size; #if 0 - info->memory = ??? info->dac_speed = ??? #endif diff --git a/src/add-ons/kernel/drivers/graphics/vesa/vesa.cpp b/src/add-ons/kernel/drivers/graphics/vesa/vesa.cpp index db038afb54..10a882ce05 100644 --- a/src/add-ons/kernel/drivers/graphics/vesa/vesa.cpp +++ b/src/add-ons/kernel/drivers/graphics/vesa/vesa.cpp @@ -24,6 +24,12 @@ #include "atombios.h" +#define LINEAR_ADDRESS(segment, offset) \ + (((addr_t)(segment) << 4) + (addr_t)(offset)) +#define SEGMENTED_TO_LINEAR(segmented) \ + LINEAR_ADDRESS((addr_t)(segmented) >> 16, (addr_t)(segmented) & 0xffff) + + static bios_module_info* sBIOSModule; @@ -194,43 +200,33 @@ vbe_to_system_dpms(uint8 vbeMode) static status_t -vbe_get_dpms_capabilities(uint32& vbeMode, uint32& mode) +vbe_get_dpms_capabilities(bios_state* state, uint32& vbeMode, uint32& mode) { // we always return a valid mode vbeMode = 0; mode = B_DPMS_ON; - // Prepare BIOS environment - bios_state* state; - status_t status = vbe_call_prepare(&state); - if (status != B_OK) - return status; - bios_regs regs = {}; regs.eax = 0x4f10; regs.ebx = 0; regs.esi = 0; regs.edi = 0; - status = sBIOSModule->interrupt(state, 0x10, ®s); + status_t status = sBIOSModule->interrupt(state, 0x10, ®s); if (status != B_OK) { dprintf(DEVICE_NAME ": vbe_get_dpms_capabilities(): BIOS failed: %s\n", strerror(status)); - goto out; + return status; } if ((regs.eax & 0xffff) != 0x4f) { dprintf(DEVICE_NAME ": vbe_get_dpms_capabilities(): BIOS returned " "0x%04" B_PRIx32 "\n", regs.eax & 0xffff); - status = B_ERROR; - goto out; + return B_ERROR; } vbeMode = regs.ebx >> 8; mode = vbe_to_system_dpms(vbeMode); - -out: - vbe_call_finish(state); return status; } @@ -263,18 +259,33 @@ vbe_set_bits_per_gun(bios_state* state, vesa_info& info, uint8 bits) static status_t -vbe_set_bits_per_gun(vesa_info& info, uint8 bits) +vbe_get_vesa_info(bios_state* state, vesa_info& info) { - info.bits_per_gun = 6; + vbe_info_block* infoHeader = (vbe_info_block*)sBIOSModule->allocate_mem(state, 256); + phys_addr_t physicalAddress = sBIOSModule->physical_address(state, infoHeader); - bios_state* state; - status_t status = vbe_call_prepare(&state); - if (status != B_OK) + bios_regs regs = {}; + regs.eax = 0x4f00; + regs.es = physicalAddress >> 4; + regs.edi = physicalAddress - (regs.es << 4); + + status_t status = sBIOSModule->interrupt(state, 0x10, ®s); + if (status != B_OK) { + dprintf(DEVICE_NAME ": vbe_get_vesa_info(): BIOS failed: %s\n", + strerror(status)); return status; + } - status = vbe_set_bits_per_gun(state, info, bits); + if ((regs.eax & 0xffff) != 0x4f) { + dprintf(DEVICE_NAME ": vbe_get_vesa_info(): BIOS returned " + "0x%04" B_PRIx32 "\n", regs.eax & 0xffff); + return B_ERROR; + } + + info.shared_info->vram_size = infoHeader->total_memory * 65536; + strlcpy(info.shared_info->name, (char*)sBIOSModule->virtual_address(state, + SEGMENTED_TO_LINEAR(infoHeader->oem_string)), 32); - vbe_call_finish(state); return status; } @@ -284,15 +295,8 @@ vbe_set_bits_per_gun(vesa_info& info, uint8 bits) * manufacturer didn't allow. */ static void -vbe_identify_bios(vesa_shared_info* sharedInfo) +vbe_identify_bios(bios_state* state, vesa_shared_info* sharedInfo) { - // TODO vbe_call_prepare/vbe_call_finish is a costly operation (loading and unloading the - // BIOS module all the time). We should try to do it less often. - bios_state* state; - status_t status = vbe_call_prepare(&state); - if (status != B_OK) - return; - // Get a pointer to the BIOS const uintptr_t kBiosBase = 0xc0000; uint8_t* bios = (uint8_t*)sBIOSModule->virtual_address(state, kBiosBase); @@ -333,8 +337,6 @@ vbe_identify_bios(vesa_shared_info* sharedInfo) } else { dprintf(DEVICE_NAME ": unknown BIOS type, custom video modes will not be available\n"); } - - vbe_call_finish(state); } @@ -464,12 +466,19 @@ vesa_init(vesa_info& info) memcpy(&sharedInfo.edid_info, edidInfo, sizeof(edid1_info)); } - vbe_identify_bios(&sharedInfo); + bios_state* state; + status_t status = vbe_call_prepare(&state); + if (status != B_OK) + return status; - vbe_get_dpms_capabilities(info.vbe_dpms_capabilities, + vbe_identify_bios(state, &sharedInfo); + + vbe_get_dpms_capabilities(state, info.vbe_dpms_capabilities, sharedInfo.dpms_capabilities); if (bufferInfo->depth <= 8) - vbe_set_bits_per_gun(info, 8); + vbe_set_bits_per_gun(state, info, 8); + + vbe_call_finish(state); dprintf(DEVICE_NAME ": vesa_init() completed successfully!\n"); return B_OK;