Updated drivers to use BIOS module instead of vm86.

This commit is contained in:
Alex Smith
2012-08-03 16:28:20 +01:00
parent b28f734b1c
commit 9f90e8a964
5 changed files with 313 additions and 231 deletions
@@ -14,7 +14,6 @@
#include <graphic_driver.h>
#ifdef __HAIKU__
#include <boot_item.h>
#include <arch/x86/vm86.h>
#endif // __HAIKU__
#include "DriverInterface.h"
@@ -8,12 +8,12 @@
#include <KernelExport.h>
#include <PCI.h>
#include <drivers/bios.h>
#include <malloc.h>
#include <stdio.h>
#include <string.h>
#include <graphic_driver.h>
#include <boot_item.h>
#include <arch/x86/vm86.h>
#include "DriverInterface.h"
@@ -249,52 +249,60 @@ GetEdidFromBIOS(edid1_raw& edidRaw)
#define ADDRESS_SEGMENT(address) ((addr_t)(address) >> 4)
#define ADDRESS_OFFSET(address) ((addr_t)(address) & 0xf)
vm86_state vmState;
status_t status = vm86_prepare(&vmState, 0x2000);
bios_module_info* biosModule;
status_t status = get_module(B_BIOS_MODULE_NAME, (module_info**)&biosModule);
if (status != B_OK) {
TRACE("GetEdidFromBIOS(); vm86_prepare() failed, status: 0x%lx\n",
TRACE("GetEdidFromBIOS(): failed to get BIOS module: 0x%" B_PRIx32 "\n",
status);
return status;
}
vmState.regs.eax = 0x4f15;
vmState.regs.ebx = 0; // 0 = report DDC service
vmState.regs.ecx = 0;
vmState.regs.es = 0;
vmState.regs.edi = 0;
bios_state* state;
status = biosModule->prepare(&state);
if (status != B_OK) {
TRACE("GetEdidFromBIOS(): bios_prepare() failed: 0x%" B_PRIx32 "\n",
status);
put_module(B_BIOS_MODULE_NAME);
return status;
}
status = vm86_do_int(&vmState, 0x10);
bios_regs regs = {};
regs.eax = 0x4f15;
regs.ebx = 0; // 0 = report DDC service
regs.ecx = 0;
regs.es = 0;
regs.edi = 0;
status = biosModule->interrupt(state, 0x10, &regs);
if (status == B_OK) {
// AH contains the error code, and AL determines whether or not the
// function is supported.
if (vmState.regs.eax != 0x4f)
if (regs.eax != 0x4f)
status = B_NOT_SUPPORTED;
// Test if DDC is supported by the monitor.
if ((vmState.regs.ebx & 3) == 0)
if ((regs.ebx & 3) == 0)
status = B_NOT_SUPPORTED;
}
if (status == B_OK) {
// According to the author of the vm86 functions, the address of any
// object to receive data must be >= 0x1000 and within the ram size
// specified in the second argument of the vm86_prepare() call above.
// Thus, the address of the struct to receive the EDID info is set to
// 0x1000.
edid1_raw* edid = (edid1_raw*)biosModule->allocate_mem(state,
sizeof(edid1_raw));
if (edid == NULL) {
status = B_NO_MEMORY;
goto out;
}
edid1_raw* edid = (edid1_raw*)0x1000;
regs.eax = 0x4f15;
regs.ebx = 1; // 1 = read EDID
regs.ecx = 0;
regs.edx = 0;
regs.es = ADDRESS_SEGMENT(edid);
regs.edi = ADDRESS_OFFSET(edid);
vmState.regs.eax = 0x4f15;
vmState.regs.ebx = 1; // 1 = read EDID
vmState.regs.ecx = 0;
vmState.regs.edx = 0;
vmState.regs.es = ADDRESS_SEGMENT(edid);
vmState.regs.edi = ADDRESS_OFFSET(edid);
status = vm86_do_int(&vmState, 0x10);
status = biosModule->interrupt(state, 0x10, &regs);
if (status == B_OK) {
if (vmState.regs.eax != 0x4f) {
if (regs.eax != 0x4f) {
status = B_NOT_SUPPORTED;
} else {
// Copy the EDID info to the caller's location, and compute the
@@ -322,8 +330,9 @@ GetEdidFromBIOS(edid1_raw& edidRaw)
}
}
vm86_cleanup(&vmState);
out:
biosModule->finish(state);
put_module(B_BIOS_MODULE_NAME);
return status;
}
@@ -336,31 +345,40 @@ SetVesaDisplayMode(uint16 mode)
#define SET_MODE_MASK 0x01ff
#define SET_MODE_LINEAR_BUFFER (1 << 14)
vm86_state vmState;
status_t status = vm86_prepare(&vmState, 0x2000);
bios_module_info* biosModule;
status_t status = get_module(B_BIOS_MODULE_NAME, (module_info**)&biosModule);
if (status != B_OK) {
TRACE("SetVesaDisplayMode(); vm86_prepare() failed, status: 0x%lx\n",
status);
TRACE("SetVesaDisplayMode(0x%x): failed to get BIOS module: 0x%" B_PRIx32
"\n", mode, status);
return status;
}
vmState.regs.eax = 0x4f02;
vmState.regs.ebx = (mode & SET_MODE_MASK) | SET_MODE_LINEAR_BUFFER;
status = vm86_do_int(&vmState, 0x10);
bios_state* state;
status = biosModule->prepare(&state);
if (status != B_OK) {
TRACE("SetVesaDisplayMode(0x%x): vm86_do_int failed\n", mode);
TRACE("SetVesaDisplayMode(0x%x): bios_prepare() failed: 0x%" B_PRIx32
"\n", mode, status);
put_module(B_BIOS_MODULE_NAME);
return status;
}
if (status == B_OK && (vmState.regs.eax & 0xffff) != 0x4f) {
TRACE("SetVesaDisplayMode(0x%x): BIOS returned 0x%04lx\n", mode,
vmState.regs.eax & 0xffff);
bios_regs regs = {};
regs.eax = 0x4f02;
regs.ebx = (mode & SET_MODE_MASK) | SET_MODE_LINEAR_BUFFER;
status = biosModule->interrupt(state, 0x10, &regs);
if (status != B_OK) {
TRACE("SetVesaDisplayMode(0x%x): BIOS interrupt failed\n", mode);
}
if (status == B_OK && (regs.eax & 0xffff) != 0x4f) {
TRACE("SetVesaDisplayMode(0x%x): BIOS returned 0x%04" B_PRIx32 "\n",
mode, regs.eax & 0xffff);
status = B_ERROR;
}
vm86_cleanup(&vmState);
biosModule->finish(state);
put_module(B_BIOS_MODULE_NAME);
return status;
}
@@ -10,12 +10,12 @@
#include <AGP.h>
#include <KernelExport.h>
#include <PCI.h>
#include <drivers/bios.h>
#include <malloc.h>
#include <stdio.h>
#include <string.h>
#include <graphic_driver.h>
#include <boot_item.h>
#include <arch/x86/vm86.h>
#include "DriverInterface.h"
@@ -148,52 +148,60 @@ GetEdidFromBIOS(edid1_raw& edidRaw)
#define ADDRESS_SEGMENT(address) ((addr_t)(address) >> 4)
#define ADDRESS_OFFSET(address) ((addr_t)(address) & 0xf)
vm86_state vmState;
status_t status = vm86_prepare(&vmState, 0x2000);
bios_module_info* biosModule;
status_t status = get_module(B_BIOS_MODULE_NAME, (module_info**)&biosModule);
if (status != B_OK) {
TRACE("GetEdidFromBIOS(); vm86_prepare() failed, status: 0x%lx\n",
TRACE("GetEdidFromBIOS(): failed to get BIOS module: 0x%" B_PRIx32 "\n",
status);
return status;
}
vmState.regs.eax = 0x4f15;
vmState.regs.ebx = 0; // 0 = report DDC service
vmState.regs.ecx = 0;
vmState.regs.es = 0;
vmState.regs.edi = 0;
bios_state* state;
status = biosModule->prepare(&state);
if (status != B_OK) {
TRACE("GetEdidFromBIOS(): bios_prepare() failed: 0x%" B_PRIx32 "\n",
status);
put_module(B_BIOS_MODULE_NAME);
return status;
}
status = vm86_do_int(&vmState, 0x10);
bios_regs regs = {};
regs.eax = 0x4f15;
regs.ebx = 0; // 0 = report DDC service
regs.ecx = 0;
regs.es = 0;
regs.edi = 0;
status = biosModule->interrupt(state, 0x10, &regs);
if (status == B_OK) {
// AH contains the error code, and AL determines wether or not the
// AH contains the error code, and AL determines whether or not the
// function is supported.
if (vmState.regs.eax != 0x4f)
if (regs.eax != 0x4f)
status = B_NOT_SUPPORTED;
// Test if DDC is supported by the monitor.
if ((vmState.regs.ebx & 3) == 0)
if ((regs.ebx & 3) == 0)
status = B_NOT_SUPPORTED;
}
if (status == B_OK) {
// According to the author of the vm86 functions, the address of any
// object to receive data must be >= 0x1000 and within the ram size
// specified in the second argument of the vm86_prepare() call above.
// Thus, the address of the struct to receive the EDID info is set to
// 0x1000.
edid1_raw* edid = (edid1_raw*)biosModule->allocate_mem(state,
sizeof(edid1_raw));
if (edid == NULL) {
status = B_NO_MEMORY;
goto out;
}
edid1_raw* edid = (edid1_raw*)0x1000;
regs.eax = 0x4f15;
regs.ebx = 1; // 1 = read EDID
regs.ecx = 0;
regs.edx = 0;
regs.es = ADDRESS_SEGMENT(edid);
regs.edi = ADDRESS_OFFSET(edid);
vmState.regs.eax = 0x4f15;
vmState.regs.ebx = 1; // 1 = read EDID
vmState.regs.ecx = 0;
vmState.regs.edx = 0;
vmState.regs.es = ADDRESS_SEGMENT(edid);
vmState.regs.edi = ADDRESS_OFFSET(edid);
status = vm86_do_int(&vmState, 0x10);
status = biosModule->interrupt(state, 0x10, &regs);
if (status == B_OK) {
if (vmState.regs.eax != 0x4f) {
if (regs.eax != 0x4f) {
status = B_NOT_SUPPORTED;
} else {
// Copy the EDID info to the caller's location, and compute the
@@ -221,9 +229,11 @@ GetEdidFromBIOS(edid1_raw& edidRaw)
}
}
vm86_cleanup(&vmState);
out:
biosModule->finish(state);
put_module(B_BIOS_MODULE_NAME);
TRACE("GetEdidFromBIOS() status: 0x%lx\n", status);
TRACE("GetEdidFromBIOS() status: 0x%" B_PRIx32 "\n", status);
return status;
}
@@ -8,13 +8,13 @@
#include <KernelExport.h>
#include <PCI.h>
#ifdef __HAIKU__
#include <drivers/bios.h>
#endif // __HAIKU__
#include <malloc.h>
#include <stdio.h>
#include <string.h>
#include <graphic_driver.h>
#ifdef __HAIKU__
#include <arch/x86/vm86.h>
#endif // __HAIKU__
#include "DriverInterface.h"
@@ -493,51 +493,60 @@ GetEdidFromBIOS(edid1_raw& edidRaw)
#define ADDRESS_SEGMENT(address) ((addr_t)(address) >> 4)
#define ADDRESS_OFFSET(address) ((addr_t)(address) & 0xf)
vm86_state vmState;
status_t status = vm86_prepare(&vmState, 0x2000);
bios_module_info* biosModule;
status_t status = get_module(B_BIOS_MODULE_NAME, (module_info**)&biosModule);
if (status != B_OK) {
TRACE("GetEdidFromBIOS(); vm86_prepare() failed, status: %lx\n", status);
TRACE("GetEdidFromBIOS(): failed to get BIOS module: 0x%" B_PRIx32 "\n",
status);
return status;
}
vmState.regs.eax = 0x4f15;
vmState.regs.ebx = 0; // 0 = report DDC service
vmState.regs.ecx = 0;
vmState.regs.es = 0;
vmState.regs.edi = 0;
bios_state* state;
status = biosModule->prepare(&state);
if (status != B_OK) {
TRACE("GetEdidFromBIOS(): bios_prepare() failed: 0x%" B_PRIx32 "\n",
status);
put_module(B_BIOS_MODULE_NAME);
return status;
}
status = vm86_do_int(&vmState, 0x10);
bios_regs regs = {};
regs.eax = 0x4f15;
regs.ebx = 0; // 0 = report DDC service
regs.ecx = 0;
regs.es = 0;
regs.edi = 0;
status = biosModule->interrupt(state, 0x10, &regs);
if (status == B_OK) {
// AH contains the error code, and AL determines whether or not the
// function is supported.
if (vmState.regs.eax != 0x4f)
if (regs.eax != 0x4f)
status = B_NOT_SUPPORTED;
// Test if DDC is supported by the monitor.
if ((vmState.regs.ebx & 3) == 0)
if ((regs.ebx & 3) == 0)
status = B_NOT_SUPPORTED;
}
if (status == B_OK) {
// According to the author of the vm86 functions, the address of any
// object to receive data must be >= 0x1000 and within the ram size
// specified in the second argument of the vm86_prepare() call above.
// Thus, the address of the struct to receive the EDID info is set to
// 0x1000.
edid1_raw* edid = (edid1_raw*)biosModule->allocate_mem(state,
sizeof(edid1_raw));
if (edid == NULL) {
status = B_NO_MEMORY;
goto out;
}
edid1_raw* edid = (edid1_raw*)0x1000;
regs.eax = 0x4f15;
regs.ebx = 1; // 1 = read EDID
regs.ecx = 0;
regs.edx = 0;
regs.es = ADDRESS_SEGMENT(edid);
regs.edi = ADDRESS_OFFSET(edid);
vmState.regs.eax = 0x4f15;
vmState.regs.ebx = 1; // 1 = read EDID
vmState.regs.ecx = 0;
vmState.regs.edx = 0;
vmState.regs.es = ADDRESS_SEGMENT(edid);
vmState.regs.edi = ADDRESS_OFFSET(edid);
status = vm86_do_int(&vmState, 0x10);
status = biosModule->interrupt(state, 0x10, &regs);
if (status == B_OK) {
if (vmState.regs.eax != 0x4f) {
if (regs.eax != 0x4f) {
status = B_NOT_SUPPORTED;
} else {
// Copy the EDID info to the caller's location, and compute the
@@ -565,9 +574,11 @@ GetEdidFromBIOS(edid1_raw& edidRaw)
}
}
vm86_cleanup(&vmState);
out:
biosModule->finish(state);
put_module(B_BIOS_MODULE_NAME);
TRACE("GetEdidFromBIOS() status: 0x%lx\n", status);
TRACE("GetEdidFromBIOS() status: 0x%" B_PRIx32 "\n", status);
return status;
}
+166 -122
View File
@@ -9,10 +9,11 @@
#include <string.h>
#include <drivers/bios.h>
#include <boot_item.h>
#include <frame_buffer_console.h>
#include <util/kernel_cpp.h>
#include <arch/x86/vm86.h>
#include <vm/vm.h>
#include "driver.h"
@@ -20,6 +21,43 @@
#include "vesa_info.h"
static 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
vbe_call_prepare(bios_state** state)
{
status_t status;
status = get_module(B_BIOS_MODULE_NAME, (module_info**)&sBIOSModule);
if (status != B_OK) {
dprintf(DEVICE_NAME ": failed to get BIOS module: %s\n",
strerror(status));
return status;
}
status = sBIOSModule->prepare(state);
if (status != B_OK) {
dprintf(DEVICE_NAME ": failed to prepare BIOS state: %s\n",
strerror(status));
put_module(B_BIOS_MODULE_NAME);
}
return status;
}
static void
vbe_call_finish(bios_state* state)
{
sBIOSModule->finish(state);
put_module(B_BIOS_MODULE_NAME);
}
static status_t
find_graphics_card(addr_t frameBuffer, addr_t& base, size_t& size)
{
@@ -80,26 +118,31 @@ get_color_space_for_depth(uint32 depth)
static status_t
vbe_get_mode_info(struct vm86_state& vmState, uint16 mode,
struct vbe_mode_info* modeInfo)
vbe_get_mode_info(bios_state* state, uint16 mode, struct vbe_mode_info* modeInfo)
{
struct vbe_mode_info* vbeModeInfo = (struct vbe_mode_info*)0x1000;
void* vbeModeInfo = sBIOSModule->allocate_mem(state,
sizeof(struct vbe_mode_info));
if (vbeModeInfo == NULL)
return B_NO_MEMORY;
memset(vbeModeInfo, 0, sizeof(vbe_mode_info));
vmState.regs.eax = 0x4f01;
vmState.regs.ecx = mode;
vmState.regs.es = 0x1000 >> 4;
vmState.regs.edi = 0x0000;
status_t status = vm86_do_int(&vmState, 0x10);
uint32 physicalAddress = sBIOSModule->physical_address(state, vbeModeInfo);
bios_regs regs = {};
regs.eax = 0x4f01;
regs.ecx = mode;
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_mode_info(%u): vm86 failed\n", mode);
dprintf(DEVICE_NAME ": vbe_get_mode_info(%u): BIOS failed: %s\n", mode,
strerror(status));
return status;
}
if ((vmState.regs.eax & 0xffff) != 0x4f) {
dprintf(DEVICE_NAME ": vbe_get_mode_info(): BIOS returned 0x%04lx\n",
vmState.regs.eax & 0xffff);
if ((regs.eax & 0xffff) != 0x4f) {
dprintf(DEVICE_NAME ": vbe_get_mode_info(%u): BIOS returned "
"0x%04" B_PRIx32 "\n", mode, regs.eax & 0xffff);
return B_ENTRY_NOT_FOUND;
}
@@ -109,20 +152,22 @@ vbe_get_mode_info(struct vm86_state& vmState, uint16 mode,
static status_t
vbe_set_mode(struct vm86_state& vmState, uint16 mode)
vbe_set_mode(bios_state* state, uint16 mode)
{
vmState.regs.eax = 0x4f02;
vmState.regs.ebx = (mode & SET_MODE_MASK) | SET_MODE_LINEAR_BUFFER;
bios_regs regs = {};
regs.eax = 0x4f02;
regs.ebx = (mode & SET_MODE_MASK) | SET_MODE_LINEAR_BUFFER;
status_t status = vm86_do_int(&vmState, 0x10);
status_t status = sBIOSModule->interrupt(state, 0x10, &regs);
if (status != B_OK) {
dprintf(DEVICE_NAME ": vbe_set_mode(%u): vm86 failed\n", mode);
dprintf(DEVICE_NAME ": vbe_set_mode(%u): BIOS failed: %s\n", mode,
strerror(status));
return status;
}
if ((vmState.regs.eax & 0xffff) != 0x4f) {
dprintf(DEVICE_NAME ": vbe_set_mode(): BIOS returned 0x%04lx\n",
vmState.regs.eax & 0xffff);
if ((regs.eax & 0xffff) != 0x4f) {
dprintf(DEVICE_NAME ": vbe_set_mode(%u): BIOS returned 0x%04" B_PRIx32
"\n", mode, regs.eax & 0xffff);
return B_ERROR;
}
@@ -152,64 +197,64 @@ vbe_get_dpms_capabilities(uint32& vbeMode, uint32& mode)
vbeMode = 0;
mode = B_DPMS_ON;
// Prepare vm86 mode environment
struct vm86_state vmState;
status_t status = vm86_prepare(&vmState, 0x20000);
if (status != B_OK) {
dprintf(DEVICE_NAME": vbe_get_dpms_capabilities(): vm86_prepare "
"failed: %s\n", strerror(status));
// Prepare BIOS environment
bios_state* state;
status_t status = vbe_call_prepare(&state);
if (status != B_OK)
return status;
}
vmState.regs.eax = 0x4f10;
vmState.regs.ebx = 0;
vmState.regs.esi = 0;
vmState.regs.edi = 0;
bios_regs regs = {};
regs.eax = 0x4f10;
regs.ebx = 0;
regs.esi = 0;
regs.edi = 0;
status = vm86_do_int(&vmState, 0x10);
status = sBIOSModule->interrupt(state, 0x10, &regs);
if (status != B_OK) {
dprintf(DEVICE_NAME ": vbe_get_dpms_capabilities(): vm86 failed\n");
dprintf(DEVICE_NAME ": vbe_get_dpms_capabilities(): BIOS failed: %s\n",
strerror(status));
goto out;
}
if ((vmState.regs.eax & 0xffff) != 0x4f) {
if ((regs.eax & 0xffff) != 0x4f) {
dprintf(DEVICE_NAME ": vbe_get_dpms_capabilities(): BIOS returned "
"0x%04lx\n", vmState.regs.eax & 0xffff);
"0x%04" B_PRIx32 "\n", regs.eax & 0xffff);
status = B_ERROR;
goto out;
}
vbeMode = vmState.regs.ebx >> 8;
vbeMode = regs.ebx >> 8;
mode = vbe_to_system_dpms(vbeMode);
out:
vm86_cleanup(&vmState);
vbe_call_finish(state);
return status;
}
static status_t
vbe_set_bits_per_gun(vm86_state& vmState, vesa_info& info, uint8 bits)
vbe_set_bits_per_gun(bios_state* state, vesa_info& info, uint8 bits)
{
info.bits_per_gun = 6;
vmState.regs.eax = 0x4f08;
vmState.regs.ebx = (bits << 8) | 1;
bios_regs regs = {};
regs.eax = 0x4f08;
regs.ebx = (bits << 8) | 1;
status_t status = vm86_do_int(&vmState, 0x10);
status_t status = sBIOSModule->interrupt(state, 0x10, &regs);
if (status != B_OK) {
dprintf(DEVICE_NAME ": vbe_set_bits_per_gun(): vm86 failed: %s\n",
dprintf(DEVICE_NAME ": vbe_set_bits_per_gun(): BIOS failed: %s\n",
strerror(status));
return status;
}
if ((vmState.regs.eax & 0xffff) != 0x4f) {
dprintf(DEVICE_NAME ": vbe_set_bits_per_gun(): BIOS returned 0x%04lx\n",
vmState.regs.eax & 0xffff);
if ((regs.eax & 0xffff) != 0x4f) {
dprintf(DEVICE_NAME ": vbe_set_bits_per_gun(): BIOS returned "
"0x%04" B_PRIx32 "\n", regs.eax & 0xffff);
return B_ERROR;
}
info.bits_per_gun = vmState.regs.ebx >> 8;
info.bits_per_gun = regs.ebx >> 8;
return B_OK;
}
@@ -219,17 +264,14 @@ vbe_set_bits_per_gun(vesa_info& info, uint8 bits)
{
info.bits_per_gun = 6;
struct vm86_state vmState;
status_t status = vm86_prepare(&vmState, 0x20000);
if (status != B_OK) {
dprintf(DEVICE_NAME": vbe_set_bits_per_gun(): vm86_prepare failed: "
"%s\n", strerror(status));
bios_state* state;
status_t status = vbe_call_prepare(&state);
if (status != B_OK)
return status;
}
status = vbe_set_bits_per_gun(vmState, info, bits);
status = vbe_set_bits_per_gun(state, info, bits);
vm86_cleanup(&vmState);
vbe_call_finish(state);
return status;
}
@@ -386,31 +428,29 @@ vesa_set_display_mode(vesa_info& info, uint32 mode)
if (mode >= info.shared_info->vesa_mode_count)
return B_ENTRY_NOT_FOUND;
// Prepare vm86 mode environment
struct vm86_state vmState;
status_t status = vm86_prepare(&vmState, 0x20000);
if (status != B_OK) {
dprintf(DEVICE_NAME": vesa_set_display_mode(): vm86_prepare failed\n");
// Prepare BIOS environment
bios_state* state;
status_t status = vbe_call_prepare(&state);
if (status != B_OK)
return status;
}
// Get mode information
struct vbe_mode_info modeInfo;
status = vbe_get_mode_info(vmState, info.modes[mode].mode, &modeInfo);
status = vbe_get_mode_info(state, info.modes[mode].mode, &modeInfo);
if (status != B_OK) {
dprintf(DEVICE_NAME": vesa_set_display_mode(): cannot get mode info\n");
goto out;
}
// Set mode
status = vbe_set_mode(vmState, info.modes[mode].mode);
status = vbe_set_mode(state, info.modes[mode].mode);
if (status != B_OK) {
dprintf(DEVICE_NAME": vesa_set_display_mode(): cannot set mode\n");
goto out;
}
if (info.modes[mode].bits_per_pixel <= 8)
vbe_set_bits_per_gun(vmState, info, 8);
vbe_set_bits_per_gun(state, info, 8);
// Map new frame buffer if necessary
@@ -426,7 +466,7 @@ vesa_set_display_mode(vesa_info& info, uint32 mode)
}
out:
vm86_cleanup(&vmState);
vbe_call_finish(state);
return status;
}
@@ -437,38 +477,36 @@ vesa_get_dpms_mode(vesa_info& info, uint32& mode)
mode = B_DPMS_ON;
// we always return a valid mode
// Prepare vm86 mode environment
struct vm86_state vmState;
status_t status = vm86_prepare(&vmState, 0x20000);
if (status != B_OK) {
dprintf(DEVICE_NAME": vesa_get_dpms_mode(): vm86_prepare failed: %s\n",
strerror(status));
// Prepare BIOS environment
bios_state* state;
status_t status = vbe_call_prepare(&state);
if (status != B_OK)
return status;
}
vmState.regs.eax = 0x4f10;
vmState.regs.ebx = 2;
vmState.regs.esi = 0;
vmState.regs.edi = 0;
bios_regs regs = {};
regs.eax = 0x4f10;
regs.ebx = 2;
regs.esi = 0;
regs.edi = 0;
status = vm86_do_int(&vmState, 0x10);
status = sBIOSModule->interrupt(state, 0x10, &regs);
if (status != B_OK) {
dprintf(DEVICE_NAME ": vesa_get_dpms_mode(): vm86 failed: %s\n",
dprintf(DEVICE_NAME ": vesa_get_dpms_mode(): BIOS failed: %s\n",
strerror(status));
goto out;
}
if ((vmState.regs.eax & 0xffff) != 0x4f) {
dprintf(DEVICE_NAME ": vesa_get_dpms_mode(): BIOS returned 0x%04lx\n",
vmState.regs.eax & 0xffff);
if ((regs.eax & 0xffff) != 0x4f) {
dprintf(DEVICE_NAME ": vesa_get_dpms_mode(): BIOS returned "
"0x%" B_PRIx32 "\n", regs.eax & 0xffff);
status = B_ERROR;
goto out;
}
mode = vbe_to_system_dpms(vmState.regs.ebx >> 8);
mode = vbe_to_system_dpms(regs.ebx >> 8);
out:
vm86_cleanup(&vmState);
vbe_call_finish(state);
return status;
}
@@ -489,36 +527,34 @@ vesa_set_dpms_mode(vesa_info& info, uint32 mode)
vbeMode &= info.vbe_dpms_capabilities;
// Prepare vm86 mode environment
struct vm86_state vmState;
status_t status = vm86_prepare(&vmState, 0x20000);
if (status != B_OK) {
dprintf(DEVICE_NAME": vesa_set_dpms_mode(): vm86_prepare failed: %s\n",
strerror(status));
// Prepare BIOS environment
bios_state* state;
status_t status = vbe_call_prepare(&state);
if (status != B_OK)
return status;
}
vmState.regs.eax = 0x4f10;
vmState.regs.ebx = (vbeMode << 8) | 1;
vmState.regs.esi = 0;
vmState.regs.edi = 0;
bios_regs regs = {};
regs.eax = 0x4f10;
regs.ebx = (vbeMode << 8) | 1;
regs.esi = 0;
regs.edi = 0;
status = vm86_do_int(&vmState, 0x10);
status = sBIOSModule->interrupt(state, 0x10, &regs);
if (status != B_OK) {
dprintf(DEVICE_NAME ": vesa_set_dpms_mode(): vm86 failed: %s\n",
dprintf(DEVICE_NAME ": vesa_set_dpms_mode(): BIOS failed: %s\n",
strerror(status));
goto out;
}
if ((vmState.regs.eax & 0xffff) != 0x4f) {
dprintf(DEVICE_NAME ": vesa_set_dpms_mode(): BIOS returned 0x%04lx\n",
vmState.regs.eax & 0xffff);
if ((regs.eax & 0xffff) != 0x4f) {
dprintf(DEVICE_NAME ": vesa_set_dpms_mode(): BIOS returned "
"0x%04" B_PRIx32 "\n", regs.eax & 0xffff);
status = B_ERROR;
goto out;
}
out:
vm86_cleanup(&vmState);
vbe_call_finish(state);
return status;
}
@@ -527,26 +563,33 @@ status_t
vesa_set_indexed_colors(vesa_info& info, uint8 first, uint8* colors,
uint16 count)
{
bios_regs regs = {};
uint32 shift, physicalAddress;
if (first + count > 256)
count = 256 - first;
// Prepare vm86 mode environment
struct vm86_state vmState;
status_t status = vm86_prepare(&vmState, 0x20000);
if (status != B_OK) {
dprintf(DEVICE_NAME": vesa_set_indexed_colors(): vm86_prepare failed: "
"%s\n", strerror(status));
// Prepare BIOS environment
bios_state* state;
status_t status = vbe_call_prepare(&state);
if (status != B_OK)
return status;
uint8* palette = (uint8*)sBIOSModule->allocate_mem(state, 256 * 4);
if (palette == NULL) {
status = B_NO_MEMORY;
goto out;
}
uint8* palette = (uint8*)0x1000;
uint32 shift = 8 - info.bits_per_gun;
shift = 8 - info.bits_per_gun;
// convert colors to VESA palette
for (int32 i = first; i < count; i++) {
uint8 color[3];
if (user_memcpy(color, &colors[i * 3], 3) < B_OK)
return B_BAD_ADDRESS;
if (user_memcpy(color, &colors[i * 3], 3) < B_OK) {
status = B_BAD_ADDRESS;
goto out;
}
// order is BGR-
palette[i * 4 + 0] = color[2] >> shift;
@@ -556,27 +599,28 @@ vesa_set_indexed_colors(vesa_info& info, uint8 first, uint8* colors,
}
// set palette
vmState.regs.eax = 0x4f09;
vmState.regs.ebx = 0;
vmState.regs.ecx = count;
vmState.regs.edx = first;
vmState.regs.es = 0x1000 >> 4;
vmState.regs.edi = 0x0000;
physicalAddress = sBIOSModule->physical_address(state, palette);
regs.eax = 0x4f09;
regs.ebx = 0;
regs.ecx = count;
regs.edx = first;
regs.es = physicalAddress >> 4;
regs.edi = physicalAddress - (regs.es << 4);
status = vm86_do_int(&vmState, 0x10);
status = sBIOSModule->interrupt(state, 0x10, &regs);
if (status != B_OK) {
dprintf(DEVICE_NAME ": vesa_set_indexed_colors(): vm86 failed: %s\n",
dprintf(DEVICE_NAME ": vesa_set_indexed_colors(): BIOS failed: %s\n",
strerror(status));
goto out;
}
if ((vmState.regs.eax & 0xffff) != 0x4f) {
if ((regs.eax & 0xffff) != 0x4f) {
dprintf(DEVICE_NAME ": vesa_set_indexed_colors(): BIOS returned "
"0x%04lx\n", vmState.regs.eax & 0xffff);
"0x%04" B_PRIx32 "\n", regs.eax & 0xffff);
status = B_ERROR;
}
out:
vm86_cleanup(&vmState);
vbe_call_finish(state);
return status;
}