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