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 <[email protected]>
Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
Adrien Destugues
2022-03-02 22:39:02 +00:00
committed by waddlesplash
parent 1005a27603
commit 6a175a5ddc
3 changed files with 68 additions and 38 deletions
@@ -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 ----------------
+22 -4
View File
@@ -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
@@ -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, &regs);
status_t status = sBIOSModule->interrupt(state, 0x10, &regs);
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, &regs);
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;