* Added DPMS support to the VESA driver, in case the hardware/BIOS supports it.
* Minor cleanup. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30974 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
08acbdd994
commit
bfd4c59b63
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2004-2008, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Copyright 2004-2009, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef VESA_H
|
||||
@ -141,6 +141,15 @@ struct crtc_info_block {
|
||||
#define CRTC_NEGATIVE_VSYNC 0x08
|
||||
|
||||
|
||||
/* Power Management */
|
||||
|
||||
#define DPMS_ON 0x00
|
||||
#define DPMS_STANDBY 0x01
|
||||
#define DPMS_SUSPEND 0x02
|
||||
#define DPMS_OFF 0x04
|
||||
#define DPMS_REDUCED_ON 0x08
|
||||
|
||||
|
||||
/* VBE 3.0 protected mode interface
|
||||
* The BIOS area can be scanned for the protected mode
|
||||
* signature that identifies the structure below.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2005-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Copyright 2005-2009, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef VESA_INFO_H
|
||||
@ -40,6 +40,7 @@ struct vesa_shared_info {
|
||||
|
||||
edid1_info edid_info;
|
||||
bool has_edid;
|
||||
uint32 dpms_capabilities;
|
||||
};
|
||||
|
||||
//----------------- ioctl() interface ----------------
|
||||
@ -49,6 +50,8 @@ enum {
|
||||
VESA_GET_PRIVATE_DATA = B_DEVICE_OP_CODES_END + 1,
|
||||
VESA_GET_DEVICE_NAME,
|
||||
VESA_SET_DISPLAY_MODE,
|
||||
VESA_GET_DPMS_MODE,
|
||||
VESA_SET_DPMS_MODE,
|
||||
|
||||
VGA_SET_INDEXED_COLORS,
|
||||
VGA_PLANAR_BLIT,
|
||||
|
@ -1,9 +1,11 @@
|
||||
/*
|
||||
* Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Copyright 2005-2009, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "accelerant_protos.h"
|
||||
#include "accelerant.h"
|
||||
|
||||
@ -11,20 +13,27 @@
|
||||
uint32
|
||||
vesa_dpms_capabilities(void)
|
||||
{
|
||||
return B_DPMS_ON;
|
||||
return gInfo->shared_info->dpms_capabilities;
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
vesa_dpms_mode(void)
|
||||
{
|
||||
return B_DPMS_ON;
|
||||
uint32 mode;
|
||||
if (ioctl(gInfo->device, VESA_GET_DPMS_MODE, &mode, sizeof(mode)) != 0)
|
||||
return B_DPMS_ON;
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
vesa_set_dpms_mode(uint32 dpms_flags)
|
||||
vesa_set_dpms_mode(uint32 mode)
|
||||
{
|
||||
return B_ERROR;
|
||||
if (ioctl(gInfo->device, VESA_SET_DPMS_MODE, &mode, sizeof(mode)) != 0)
|
||||
return errno;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
/*
|
||||
* Copyright 2005-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Copyright 2005-2009, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <create_display_modes.h>
|
||||
@ -14,7 +15,7 @@
|
||||
|
||||
//#define TRACE_MODE
|
||||
#ifdef TRACE_MODE
|
||||
extern "C" void _sPrintf(const char *format, ...);
|
||||
extern "C" void _sPrintf(const char* format, ...);
|
||||
# define TRACE(x) _sPrintf x
|
||||
#else
|
||||
# define TRACE(x) ;
|
||||
@ -46,9 +47,9 @@ get_color_space_for_depth(uint32 depth)
|
||||
|
||||
/*! Checks if the specified \a mode can be set using VESA. */
|
||||
static bool
|
||||
is_mode_supported(display_mode *mode)
|
||||
is_mode_supported(display_mode* mode)
|
||||
{
|
||||
vesa_mode *modes = gInfo->vesa_modes;
|
||||
vesa_mode* modes = gInfo->vesa_modes;
|
||||
|
||||
for (uint32 i = gInfo->shared_info->vesa_mode_count; i-- > 0;) {
|
||||
// search mode in VESA mode list
|
||||
@ -96,7 +97,7 @@ vesa_accelerant_mode_count(void)
|
||||
|
||||
|
||||
status_t
|
||||
vesa_get_mode_list(display_mode *modeList)
|
||||
vesa_get_mode_list(display_mode* modeList)
|
||||
{
|
||||
TRACE(("vesa_get_mode_info()\n"));
|
||||
memcpy(modeList, gInfo->mode_list,
|
||||
@ -106,15 +107,15 @@ vesa_get_mode_list(display_mode *modeList)
|
||||
|
||||
|
||||
status_t
|
||||
vesa_propose_display_mode(display_mode *target, const display_mode *low,
|
||||
const display_mode *high)
|
||||
vesa_propose_display_mode(display_mode* target, const display_mode* low,
|
||||
const display_mode* high)
|
||||
{
|
||||
TRACE(("vesa_propose_display_mode()\n"));
|
||||
|
||||
// just search for the specified mode in the list
|
||||
|
||||
for (uint32 i = 0; i < gInfo->shared_info->mode_count; i++) {
|
||||
display_mode *current = &gInfo->mode_list[i];
|
||||
display_mode* current = &gInfo->mode_list[i];
|
||||
|
||||
if (target->virtual_width != current->virtual_width
|
||||
|| target->virtual_height != current->virtual_height
|
||||
@ -129,7 +130,7 @@ vesa_propose_display_mode(display_mode *target, const display_mode *low,
|
||||
|
||||
|
||||
status_t
|
||||
vesa_set_display_mode(display_mode *_mode)
|
||||
vesa_set_display_mode(display_mode* _mode)
|
||||
{
|
||||
TRACE(("vesa_set_display_mode()\n"));
|
||||
|
||||
@ -137,8 +138,8 @@ vesa_set_display_mode(display_mode *_mode)
|
||||
if (vesa_propose_display_mode(&mode, &mode, &mode) != B_OK)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
vesa_mode *modes = gInfo->vesa_modes;
|
||||
for (unsigned int i = gInfo->shared_info->vesa_mode_count; i-- > 0;) {
|
||||
vesa_mode* modes = gInfo->vesa_modes;
|
||||
for (uint32 i = gInfo->shared_info->vesa_mode_count; i-- > 0;) {
|
||||
// search mode in VESA mode list
|
||||
// TODO: list is ordered, we could use binary search
|
||||
if (modes[i].width == mode.virtual_width
|
||||
@ -153,7 +154,7 @@ vesa_set_display_mode(display_mode *_mode)
|
||||
|
||||
|
||||
status_t
|
||||
vesa_get_display_mode(display_mode *_currentMode)
|
||||
vesa_get_display_mode(display_mode* _currentMode)
|
||||
{
|
||||
TRACE(("vesa_get_display_mode()\n"));
|
||||
*_currentMode = gInfo->shared_info->current_mode;
|
||||
@ -162,7 +163,7 @@ vesa_get_display_mode(display_mode *_currentMode)
|
||||
|
||||
|
||||
status_t
|
||||
vesa_get_edid_info(void *info, size_t size, uint32 *_version)
|
||||
vesa_get_edid_info(void* info, size_t size, uint32* _version)
|
||||
{
|
||||
TRACE(("intel_get_edid_info()\n"));
|
||||
|
||||
@ -178,7 +179,7 @@ vesa_get_edid_info(void *info, size_t size, uint32 *_version)
|
||||
|
||||
|
||||
status_t
|
||||
vesa_get_frame_buffer_config(frame_buffer_config *config)
|
||||
vesa_get_frame_buffer_config(frame_buffer_config* config)
|
||||
{
|
||||
TRACE(("vesa_get_frame_buffer_config()\n"));
|
||||
|
||||
@ -191,20 +192,21 @@ vesa_get_frame_buffer_config(frame_buffer_config *config)
|
||||
|
||||
|
||||
status_t
|
||||
vesa_get_pixel_clock_limits(display_mode *mode, uint32 *low, uint32 *high)
|
||||
vesa_get_pixel_clock_limits(display_mode* mode, uint32* low, uint32* high)
|
||||
{
|
||||
TRACE(("vesa_get_pixel_clock_limits()\n"));
|
||||
|
||||
// ToDo: do some real stuff here (taken from radeon driver)
|
||||
uint32 total_pix = (uint32)mode->timing.h_total * (uint32)mode->timing.v_total;
|
||||
uint32 clock_limit = 2000000;
|
||||
// TODO: do some real stuff here (taken from radeon driver)
|
||||
uint32 totalPixel = (uint32)mode->timing.h_total
|
||||
* (uint32)mode->timing.v_total;
|
||||
uint32 clockLimit = 2000000;
|
||||
|
||||
/* lower limit of about 48Hz vertical refresh */
|
||||
*low = (total_pix * 48L) / 1000L;
|
||||
if (*low > clock_limit)
|
||||
// lower limit of about 48Hz vertical refresh
|
||||
*low = totalPixel * 48L / 1000L;
|
||||
if (*low > clockLimit)
|
||||
return B_ERROR;
|
||||
|
||||
*high = clock_limit;
|
||||
*high = clockLimit;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@ -218,7 +220,7 @@ vesa_move_display(uint16 h_display_start, uint16 v_display_start)
|
||||
|
||||
|
||||
status_t
|
||||
vesa_get_timing_constraints(display_timing_constraints *dtc)
|
||||
vesa_get_timing_constraints(display_timing_constraints* constraints)
|
||||
{
|
||||
TRACE(("vesa_get_timing_constraints()\n"));
|
||||
return B_ERROR;
|
||||
@ -226,7 +228,7 @@ vesa_get_timing_constraints(display_timing_constraints *dtc)
|
||||
|
||||
|
||||
void
|
||||
vesa_set_indexed_colors(uint count, uint8 first, uint8 *colors, uint32 flags)
|
||||
vesa_set_indexed_colors(uint count, uint8 first, uint8* colors, uint32 flags)
|
||||
{
|
||||
TRACE(("vesa_set_indexed_colors()\n"));
|
||||
vga_set_indexed_colors_args args;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2005-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Copyright 2005-2009, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
@ -32,53 +32,23 @@
|
||||
#endif
|
||||
|
||||
|
||||
/* device hooks prototypes */
|
||||
|
||||
static status_t device_open(const char *, uint32, void **);
|
||||
static status_t device_close(void *);
|
||||
static status_t device_free(void *);
|
||||
static status_t device_ioctl(void *, uint32, void *, size_t);
|
||||
static status_t device_read(void *, off_t, void *, size_t *);
|
||||
static status_t device_write(void *, off_t, const void *, size_t *);
|
||||
|
||||
|
||||
device_hooks gDeviceHooks = {
|
||||
device_open,
|
||||
device_close,
|
||||
device_free,
|
||||
device_ioctl,
|
||||
device_read,
|
||||
device_write,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
// the device will be accessed through the following functions (a.k.a. device hooks)
|
||||
|
||||
|
||||
static status_t
|
||||
device_open(const char *name, uint32 flags, void **_cookie)
|
||||
device_open(const char* name, uint32 flags, void** _cookie)
|
||||
{
|
||||
int id;
|
||||
|
||||
// find accessed device
|
||||
{
|
||||
char *thisName;
|
||||
char* thisName;
|
||||
|
||||
// search for device name
|
||||
for (id = 0; (thisName = gDeviceNames[id]) != NULL; id++) {
|
||||
if (!strcmp(name, thisName))
|
||||
break;
|
||||
}
|
||||
if (!thisName)
|
||||
return EINVAL;
|
||||
// search for device name
|
||||
for (id = 0; (thisName = gDeviceNames[id]) != NULL; id++) {
|
||||
if (!strcmp(name, thisName))
|
||||
break;
|
||||
}
|
||||
if (thisName == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
vesa_info *info = gDeviceInfo[id];
|
||||
vesa_info* info = gDeviceInfo[id];
|
||||
*_cookie = info;
|
||||
|
||||
acquire_lock(&gLock);
|
||||
@ -100,16 +70,16 @@ device_open(const char *name, uint32 flags, void **_cookie)
|
||||
|
||||
|
||||
static status_t
|
||||
device_close(void *cookie)
|
||||
device_close(void* cookie)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
device_free(void *cookie)
|
||||
device_free(void* cookie)
|
||||
{
|
||||
struct vesa_info *info = (vesa_info *)cookie;
|
||||
struct vesa_info* info = (vesa_info*)cookie;
|
||||
|
||||
acquire_lock(&gLock);
|
||||
|
||||
@ -124,26 +94,26 @@ device_free(void *cookie)
|
||||
|
||||
|
||||
static status_t
|
||||
device_ioctl(void *cookie, uint32 msg, void *buffer, size_t bufferLength)
|
||||
device_ioctl(void* cookie, uint32 msg, void* buffer, size_t bufferLength)
|
||||
{
|
||||
struct vesa_info *info = (vesa_info *)cookie;
|
||||
struct vesa_info* info = (vesa_info*)cookie;
|
||||
|
||||
switch (msg) {
|
||||
case B_GET_ACCELERANT_SIGNATURE:
|
||||
dprintf(DEVICE_NAME ": acc: %s\n", VESA_ACCELERANT_NAME);
|
||||
if (user_strlcpy((char *)buffer, VESA_ACCELERANT_NAME,
|
||||
if (user_strlcpy((char*)buffer, VESA_ACCELERANT_NAME,
|
||||
B_FILE_NAME_LENGTH) < B_OK)
|
||||
return B_BAD_ADDRESS;
|
||||
|
||||
return B_OK;
|
||||
|
||||
// needed to share data between kernel and accelerant
|
||||
// needed to share data between kernel and accelerant
|
||||
case VESA_GET_PRIVATE_DATA:
|
||||
return user_memcpy(buffer, &info->shared_area, sizeof(area_id));
|
||||
|
||||
// needed for cloning
|
||||
case VESA_GET_DEVICE_NAME:
|
||||
if (user_strlcpy((char *)buffer, gDeviceNames[info->id],
|
||||
if (user_strlcpy((char*)buffer, gDeviceNames[info->id],
|
||||
B_PATH_NAME_LENGTH) < B_OK)
|
||||
return B_BAD_ADDRESS;
|
||||
|
||||
@ -151,15 +121,41 @@ device_ioctl(void *cookie, uint32 msg, void *buffer, size_t bufferLength)
|
||||
|
||||
case VESA_SET_DISPLAY_MODE:
|
||||
{
|
||||
unsigned int mode;
|
||||
if (bufferLength != sizeof(uint32))
|
||||
return B_BAD_VALUE;
|
||||
|
||||
if (bufferLength != sizeof(mode)
|
||||
|| user_memcpy(&mode, buffer, sizeof(mode)) < B_OK)
|
||||
uint32 mode;
|
||||
if (user_memcpy(&mode, buffer, sizeof(uint32)) < B_OK)
|
||||
return B_BAD_ADDRESS;
|
||||
|
||||
return vesa_set_display_mode(*info, mode);
|
||||
}
|
||||
|
||||
case VESA_GET_DPMS_MODE:
|
||||
{
|
||||
if (bufferLength != sizeof(uint32))
|
||||
return B_BAD_VALUE;
|
||||
|
||||
uint32 mode;
|
||||
status_t status = vesa_get_dpms_mode(*info, mode);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
return user_memcpy(buffer, &mode, sizeof(mode));
|
||||
}
|
||||
|
||||
case VESA_SET_DPMS_MODE:
|
||||
{
|
||||
if (bufferLength != sizeof(uint32))
|
||||
return B_BAD_VALUE;
|
||||
|
||||
uint32 mode;
|
||||
if (user_memcpy(&mode, buffer, sizeof(uint32)) < B_OK)
|
||||
return B_BAD_ADDRESS;
|
||||
|
||||
return vesa_set_dpms_mode(*info, mode);
|
||||
}
|
||||
|
||||
case VGA_SET_INDEXED_COLORS:
|
||||
{
|
||||
vga_set_indexed_colors_args args;
|
||||
@ -181,7 +177,9 @@ device_ioctl(void *cookie, uint32 msg, void *buffer, size_t bufferLength)
|
||||
}
|
||||
|
||||
default:
|
||||
TRACE((DEVICE_NAME ": ioctl() unknown message %ld (length = %lu)\n", msg, bufferLength));
|
||||
TRACE((DEVICE_NAME ": ioctl() unknown message %ld (length = %lu)\n",
|
||||
msg, bufferLength));
|
||||
break;
|
||||
}
|
||||
|
||||
return B_DEV_INVALID_IOCTL;
|
||||
@ -189,17 +187,31 @@ device_ioctl(void *cookie, uint32 msg, void *buffer, size_t bufferLength)
|
||||
|
||||
|
||||
static status_t
|
||||
device_read(void */*cookie*/, off_t /*pos*/, void */*buffer*/, size_t *_length)
|
||||
device_read(void* /*cookie*/, off_t /*pos*/, void* /*buffer*/, size_t* _length)
|
||||
{
|
||||
*_length = 0;
|
||||
*_length = 0;
|
||||
return B_NOT_ALLOWED;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
device_write(void */*cookie*/, off_t /*pos*/, const void */*buffer*/, size_t *_length)
|
||||
device_write(void* /*cookie*/, off_t /*pos*/, const void* /*buffer*/,
|
||||
size_t* _length)
|
||||
{
|
||||
*_length = 0;
|
||||
*_length = 0;
|
||||
return B_NOT_ALLOWED;
|
||||
}
|
||||
|
||||
|
||||
device_hooks gDeviceHooks = {
|
||||
device_open,
|
||||
device_close,
|
||||
device_free,
|
||||
device_ioctl,
|
||||
device_read,
|
||||
device_write,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2005-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Copyright 2005-2009, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
@ -44,26 +44,26 @@ 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(struct vm86_state& vmState, uint16 mode,
|
||||
struct vbe_mode_info* modeInfo)
|
||||
{
|
||||
struct vbe_mode_info *vbeModeInfo = (struct vbe_mode_info *)0x1000;
|
||||
struct vbe_mode_info* vbeModeInfo = (struct vbe_mode_info*)0x1000;
|
||||
|
||||
memset(vbeModeInfo, 0, sizeof(vbe_mode_info));
|
||||
vmState->regs.eax = 0x4f01;
|
||||
vmState->regs.ecx = mode;
|
||||
vmState->regs.es = 0x1000 >> 4;
|
||||
vmState->regs.edi = 0x0000;
|
||||
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);
|
||||
status_t status = vm86_do_int(&vmState, 0x10);
|
||||
if (status != B_OK) {
|
||||
dprintf(DEVICE_NAME ": vbe_get_mode_info(%u): vm86 failed\n", mode);
|
||||
return status;
|
||||
}
|
||||
|
||||
if ((vmState->regs.eax & 0xffff) != 0x4f) {
|
||||
if ((vmState.regs.eax & 0xffff) != 0x4f) {
|
||||
dprintf(DEVICE_NAME ": vbe_get_mode_info(): BIOS returned 0x%04lx\n",
|
||||
vmState->regs.eax & 0xffff);
|
||||
vmState.regs.eax & 0xffff);
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
}
|
||||
|
||||
@ -73,20 +73,20 @@ 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(struct vm86_state& vmState, uint16 mode)
|
||||
{
|
||||
vmState->regs.eax = 0x4f02;
|
||||
vmState->regs.ebx = (mode & SET_MODE_MASK) | SET_MODE_LINEAR_BUFFER;
|
||||
vmState.regs.eax = 0x4f02;
|
||||
vmState.regs.ebx = (mode & SET_MODE_MASK) | SET_MODE_LINEAR_BUFFER;
|
||||
|
||||
status_t status = vm86_do_int(vmState, 0x10);
|
||||
status_t status = vm86_do_int(&vmState, 0x10);
|
||||
if (status != B_OK) {
|
||||
dprintf(DEVICE_NAME ": vbe_set_mode(%u): vm86 failed\n", mode);
|
||||
return status;
|
||||
}
|
||||
|
||||
if ((vmState->regs.eax & 0xffff) != 0x4f) {
|
||||
if ((vmState.regs.eax & 0xffff) != 0x4f) {
|
||||
dprintf(DEVICE_NAME ": vbe_set_mode(): BIOS returned 0x%04lx\n",
|
||||
vmState->regs.eax & 0xffff);
|
||||
vmState.regs.eax & 0xffff);
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
@ -94,26 +94,84 @@ vbe_set_mode(struct vm86_state *vmState, uint16 mode)
|
||||
}
|
||||
|
||||
|
||||
static uint32
|
||||
vbe_to_system_dpms(uint8 vbeMode)
|
||||
{
|
||||
uint32 mode = 0;
|
||||
if ((vbeMode & (DPMS_OFF | DPMS_REDUCED_ON)) != 0)
|
||||
mode |= B_DPMS_OFF;
|
||||
if ((vbeMode & DPMS_STANDBY) != 0)
|
||||
mode |= B_DPMS_STAND_BY;
|
||||
if ((vbeMode & DPMS_SUSPEND) != 0)
|
||||
mode |= B_DPMS_SUSPEND;
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
vbe_get_dpms_capabilities(uint32& vbeMode, uint32& mode)
|
||||
{
|
||||
// we always return a valid 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));
|
||||
return status;
|
||||
}
|
||||
|
||||
vmState.regs.eax = 0x4f10;
|
||||
vmState.regs.ebx = 0;
|
||||
vmState.regs.esi = 0;
|
||||
vmState.regs.edi = 0;
|
||||
|
||||
status = vm86_do_int(&vmState, 0x10);
|
||||
if (status != B_OK) {
|
||||
dprintf(DEVICE_NAME ": vbe_get_dpms_capabilities(): vm86 failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((vmState.regs.eax & 0xffff) != 0x4f) {
|
||||
dprintf(DEVICE_NAME ": vbe_get_dpms_capabilities(): BIOS returned "
|
||||
"0x%04lx\n", vmState.regs.eax & 0xffff);
|
||||
status = B_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
vbeMode = vmState.regs.ebx >> 8;
|
||||
mode = vbe_to_system_dpms(vbeMode);
|
||||
|
||||
out:
|
||||
vm86_cleanup(&vmState);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
status_t
|
||||
vesa_init(vesa_info &info)
|
||||
vesa_init(vesa_info& info)
|
||||
{
|
||||
frame_buffer_boot_info *bufferInfo
|
||||
= (frame_buffer_boot_info *)get_boot_item(FRAME_BUFFER_BOOT_INFO, NULL);
|
||||
frame_buffer_boot_info* bufferInfo
|
||||
= (frame_buffer_boot_info*)get_boot_item(FRAME_BUFFER_BOOT_INFO, NULL);
|
||||
if (bufferInfo == NULL)
|
||||
return B_ERROR;
|
||||
|
||||
size_t modesSize = 0;
|
||||
vesa_mode *modes = (vesa_mode *)get_boot_item(VESA_MODES_BOOT_INFO,
|
||||
vesa_mode* modes = (vesa_mode*)get_boot_item(VESA_MODES_BOOT_INFO,
|
||||
&modesSize);
|
||||
info.modes = modes;
|
||||
|
||||
size_t sharedSize = (sizeof(vesa_shared_info) + 7) & ~7;
|
||||
|
||||
info.shared_area = create_area("vesa shared info",
|
||||
(void **)&info.shared_info, B_ANY_KERNEL_ADDRESS,
|
||||
(void**)&info.shared_info, B_ANY_KERNEL_ADDRESS,
|
||||
ROUND_TO_PAGE_SIZE(sharedSize + modesSize), B_FULL_LOCK,
|
||||
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA | B_USER_CLONEABLE_AREA);
|
||||
if (info.shared_area < B_OK)
|
||||
@ -131,7 +189,7 @@ vesa_init(vesa_info &info)
|
||||
}
|
||||
|
||||
sharedInfo.frame_buffer_area = bufferInfo->area;
|
||||
sharedInfo.frame_buffer = (uint8 *)bufferInfo->frame_buffer;
|
||||
sharedInfo.frame_buffer = (uint8*)bufferInfo->frame_buffer;
|
||||
|
||||
sharedInfo.current_mode.virtual_width = bufferInfo->width;
|
||||
sharedInfo.current_mode.virtual_height = bufferInfo->height;
|
||||
@ -140,17 +198,19 @@ vesa_init(vesa_info &info)
|
||||
sharedInfo.bytes_per_row = bufferInfo->bytes_per_row;
|
||||
|
||||
// TODO: we might want to do this via vm86 instead
|
||||
edid1_info *edidInfo = (edid1_info *)get_boot_item(VESA_EDID_BOOT_INFO,
|
||||
edid1_info* edidInfo = (edid1_info*)get_boot_item(VESA_EDID_BOOT_INFO,
|
||||
NULL);
|
||||
if (edidInfo != NULL) {
|
||||
sharedInfo.has_edid = true;
|
||||
memcpy(&sharedInfo.edid_info, edidInfo, sizeof(edid1_info));
|
||||
}
|
||||
|
||||
vbe_get_dpms_capabilities(info.vbe_dpms_capabilities,
|
||||
sharedInfo.dpms_capabilities);
|
||||
|
||||
physical_entry mapping;
|
||||
get_memory_map((void *)sharedInfo.frame_buffer, B_PAGE_SIZE,
|
||||
&mapping, 1);
|
||||
sharedInfo.physical_frame_buffer = (uint8 *)mapping.address;
|
||||
get_memory_map((void*)sharedInfo.frame_buffer, B_PAGE_SIZE, &mapping, 1);
|
||||
sharedInfo.physical_frame_buffer = (uint8*)mapping.address;
|
||||
|
||||
dprintf(DEVICE_NAME ": vesa_init() completed successfully!\n");
|
||||
return B_OK;
|
||||
@ -158,7 +218,7 @@ vesa_init(vesa_info &info)
|
||||
|
||||
|
||||
void
|
||||
vesa_uninit(vesa_info &info)
|
||||
vesa_uninit(vesa_info& info)
|
||||
{
|
||||
dprintf(DEVICE_NAME": vesa_uninit()\n");
|
||||
|
||||
@ -168,7 +228,7 @@ vesa_uninit(vesa_info &info)
|
||||
|
||||
|
||||
status_t
|
||||
vesa_set_display_mode(vesa_info &info, unsigned int mode)
|
||||
vesa_set_display_mode(vesa_info& info, uint32 mode)
|
||||
{
|
||||
if (mode >= info.shared_info->vesa_mode_count)
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
@ -181,43 +241,42 @@ vesa_set_display_mode(vesa_info &info, unsigned int mode)
|
||||
return status;
|
||||
}
|
||||
|
||||
area_id newFBArea;
|
||||
frame_buffer_boot_info *bufferInfo;
|
||||
area_id frameBufferArea;
|
||||
frame_buffer_boot_info* bufferInfo;
|
||||
struct vbe_mode_info modeInfo;
|
||||
|
||||
// Get mode information
|
||||
status = vbe_get_mode_info(&vmState, info.modes[mode].mode, &modeInfo);
|
||||
status = vbe_get_mode_info(vmState, info.modes[mode].mode, &modeInfo);
|
||||
if (status != B_OK) {
|
||||
dprintf(DEVICE_NAME": vesa_set_display_mode(): cannot get mode info\n");
|
||||
goto error;
|
||||
goto out;
|
||||
}
|
||||
|
||||
// Set mode
|
||||
status = vbe_set_mode(&vmState, info.modes[mode].mode);
|
||||
status = vbe_set_mode(vmState, info.modes[mode].mode);
|
||||
if (status != B_OK) {
|
||||
dprintf(DEVICE_NAME": vesa_set_display_mode(): cannot set mode\n");
|
||||
goto error;
|
||||
goto out;
|
||||
}
|
||||
|
||||
// Map new frame buffer
|
||||
void *frameBuffer;
|
||||
newFBArea = map_physical_memory("vesa_fb",
|
||||
(void *)modeInfo.physical_base,
|
||||
modeInfo.bytes_per_row * modeInfo.height, B_ANY_KERNEL_ADDRESS,
|
||||
B_READ_AREA | B_WRITE_AREA, &frameBuffer);
|
||||
if (newFBArea < B_OK) {
|
||||
status = (status_t)newFBArea;
|
||||
goto error;
|
||||
void* frameBuffer;
|
||||
frameBufferArea = map_physical_memory("vesa_fb",
|
||||
(void*)modeInfo.physical_base, modeInfo.bytes_per_row * modeInfo.height,
|
||||
B_ANY_KERNEL_ADDRESS, B_READ_AREA | B_WRITE_AREA, &frameBuffer);
|
||||
if (frameBufferArea < B_OK) {
|
||||
status = (status_t)frameBufferArea;
|
||||
goto out;
|
||||
}
|
||||
delete_area(info.shared_info->frame_buffer_area);
|
||||
|
||||
// Turn on write combining for the area
|
||||
vm_set_area_memory_type(newFBArea, modeInfo.physical_base, B_MTR_WC);
|
||||
vm_set_area_memory_type(frameBufferArea, modeInfo.physical_base, B_MTR_WC);
|
||||
|
||||
// Update shared frame buffer information
|
||||
info.shared_info->frame_buffer_area = newFBArea;
|
||||
info.shared_info->frame_buffer = (uint8 *)frameBuffer;
|
||||
info.shared_info->physical_frame_buffer = (uint8 *)modeInfo.physical_base;
|
||||
info.shared_info->frame_buffer_area = frameBufferArea;
|
||||
info.shared_info->frame_buffer = (uint8*)frameBuffer;
|
||||
info.shared_info->physical_frame_buffer = (uint8*)modeInfo.physical_base;
|
||||
info.shared_info->bytes_per_row = modeInfo.bytes_per_row;
|
||||
info.shared_info->current_mode.virtual_width = modeInfo.width;
|
||||
info.shared_info->current_mode.virtual_height = modeInfo.height;
|
||||
@ -226,16 +285,107 @@ vesa_set_display_mode(vesa_info &info, unsigned int mode)
|
||||
|
||||
// Update boot item as it's used in vesa_init()
|
||||
bufferInfo
|
||||
= (frame_buffer_boot_info *)get_boot_item(FRAME_BUFFER_BOOT_INFO, NULL);
|
||||
bufferInfo->area = newFBArea;
|
||||
= (frame_buffer_boot_info*)get_boot_item(FRAME_BUFFER_BOOT_INFO, NULL);
|
||||
bufferInfo->area = frameBufferArea;
|
||||
bufferInfo->frame_buffer = (addr_t)frameBuffer;
|
||||
bufferInfo->width = modeInfo.width;
|
||||
bufferInfo->height = modeInfo.height;
|
||||
bufferInfo->depth = modeInfo.bits_per_pixel;
|
||||
bufferInfo->bytes_per_row = modeInfo.bytes_per_row;
|
||||
|
||||
error:
|
||||
out:
|
||||
vm86_cleanup(&vmState);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
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));
|
||||
return status;
|
||||
}
|
||||
|
||||
vmState.regs.eax = 0x4f10;
|
||||
vmState.regs.ebx = 2;
|
||||
vmState.regs.esi = 0;
|
||||
vmState.regs.edi = 0;
|
||||
|
||||
status = vm86_do_int(&vmState, 0x10);
|
||||
if (status != B_OK) {
|
||||
dprintf(DEVICE_NAME ": vesa_get_dpms_mode(): vm86 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);
|
||||
status = B_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
mode = vbe_to_system_dpms(vmState.regs.ebx >> 8);
|
||||
|
||||
out:
|
||||
vm86_cleanup(&vmState);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
vesa_set_dpms_mode(vesa_info& info, uint32 mode)
|
||||
{
|
||||
// Only let supported modes through
|
||||
mode &= info.shared_info->dpms_capabilities;
|
||||
|
||||
uint8 vbeMode = 0;
|
||||
if ((mode & B_DPMS_OFF) != 0)
|
||||
vbeMode |= DPMS_OFF | DPMS_REDUCED_ON;
|
||||
if ((mode & B_DPMS_STAND_BY) != 0)
|
||||
vbeMode |= DPMS_STANDBY;
|
||||
if ((mode & B_DPMS_SUSPEND) != 0)
|
||||
vbeMode |= DPMS_SUSPEND;
|
||||
|
||||
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));
|
||||
return status;
|
||||
}
|
||||
|
||||
vmState.regs.eax = 0x4f10;
|
||||
vmState.regs.ebx = (vbeMode << 8) | 1;
|
||||
vmState.regs.esi = 0;
|
||||
vmState.regs.edi = 0;
|
||||
|
||||
status = vm86_do_int(&vmState, 0x10);
|
||||
if (status != B_OK) {
|
||||
dprintf(DEVICE_NAME ": vesa_set_dpms_mode(): vm86 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);
|
||||
status = B_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
vm86_cleanup(&vmState);
|
||||
return status;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2005-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Copyright 2005-2009, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef VESA_PRIVATE_H
|
||||
@ -22,14 +22,17 @@ struct vesa_info {
|
||||
uint32 cookie_magic;
|
||||
int32 open_count;
|
||||
int32 id;
|
||||
pci_info *pci;
|
||||
struct vesa_shared_info *shared_info;
|
||||
pci_info* pci;
|
||||
struct vesa_shared_info* shared_info;
|
||||
area_id shared_area;
|
||||
vesa_mode *modes;
|
||||
vesa_mode* modes;
|
||||
uint32 vbe_dpms_capabilities;
|
||||
};
|
||||
|
||||
extern status_t vesa_init(vesa_info &info);
|
||||
extern void vesa_uninit(vesa_info &info);
|
||||
extern status_t vesa_set_display_mode(vesa_info &info, unsigned int mode);
|
||||
extern status_t vesa_init(vesa_info& info);
|
||||
extern void vesa_uninit(vesa_info& info);
|
||||
extern status_t vesa_set_display_mode(vesa_info& info, uint32 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);
|
||||
|
||||
#endif /* VESA_PRIVATE_H */
|
||||
|
Loading…
Reference in New Issue
Block a user