[Haiku-commits] r30974 - in haiku/trunk: headers/private/graphics/vesa src/add-ons/accelerants/vesa src/add-ons/kernel/drivers/graphics/vesa

axeld at BerliOS axeld at mail.berlios.de
Fri Jun 5 15:03:06 CEST 2009


Author: axeld
Date: 2009-06-05 15:03:05 +0200 (Fri, 05 Jun 2009)
New Revision: 30974
ViewCVS: http://svn.berlios.de/viewcvs/haiku?rev=30974&view=rev

Modified:
   haiku/trunk/headers/private/graphics/vesa/vesa.h
   haiku/trunk/headers/private/graphics/vesa/vesa_info.h
   haiku/trunk/src/add-ons/accelerants/vesa/dpms.cpp
   haiku/trunk/src/add-ons/accelerants/vesa/mode.cpp
   haiku/trunk/src/add-ons/kernel/drivers/graphics/vesa/device.cpp
   haiku/trunk/src/add-ons/kernel/drivers/graphics/vesa/vesa.cpp
   haiku/trunk/src/add-ons/kernel/drivers/graphics/vesa/vesa_private.h
Log:
* Added DPMS support to the VESA driver, in case the hardware/BIOS supports it.
* Minor cleanup.


Modified: haiku/trunk/headers/private/graphics/vesa/vesa.h
===================================================================
--- haiku/trunk/headers/private/graphics/vesa/vesa.h	2009-06-05 12:33:22 UTC (rev 30973)
+++ haiku/trunk/headers/private/graphics/vesa/vesa.h	2009-06-05 13:03:05 UTC (rev 30974)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2004-2008, Axel Dörfler, axeld at pinc-software.de.
+ * Copyright 2004-2009, Axel Dörfler, axeld at pinc-software.de.
  * Distributed under the terms of the MIT License.
  */
 #ifndef VESA_H
@@ -141,6 +141,15 @@
 #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.

Modified: haiku/trunk/headers/private/graphics/vesa/vesa_info.h
===================================================================
--- haiku/trunk/headers/private/graphics/vesa/vesa_info.h	2009-06-05 12:33:22 UTC (rev 30973)
+++ haiku/trunk/headers/private/graphics/vesa/vesa_info.h	2009-06-05 13:03:05 UTC (rev 30974)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2005-2008, Axel Dörfler, axeld at pinc-software.de. All rights reserved.
+ * Copyright 2005-2009, Axel Dörfler, axeld at pinc-software.de.
  * Distributed under the terms of the MIT License.
  */
 #ifndef VESA_INFO_H
@@ -40,6 +40,7 @@
 
 	edid1_info		edid_info;
 	bool			has_edid;
+	uint32			dpms_capabilities;
 };
 
 //----------------- ioctl() interface ----------------
@@ -49,6 +50,8 @@
 	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,

Modified: haiku/trunk/src/add-ons/accelerants/vesa/dpms.cpp
===================================================================
--- haiku/trunk/src/add-ons/accelerants/vesa/dpms.cpp	2009-06-05 12:33:22 UTC (rev 30973)
+++ haiku/trunk/src/add-ons/accelerants/vesa/dpms.cpp	2009-06-05 13:03:05 UTC (rev 30974)
@@ -1,9 +1,11 @@
 /*
- * Copyright 2005, Axel Dörfler, axeld at pinc-software.de. All rights reserved.
+ * Copyright 2005-2009, Axel Dörfler, axeld at 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;
 }
 

Modified: haiku/trunk/src/add-ons/accelerants/vesa/mode.cpp
===================================================================
--- haiku/trunk/src/add-ons/accelerants/vesa/mode.cpp	2009-06-05 12:33:22 UTC (rev 30973)
+++ haiku/trunk/src/add-ons/accelerants/vesa/mode.cpp	2009-06-05 13:03:05 UTC (rev 30974)
@@ -1,8 +1,9 @@
 /*
- * Copyright 2005-2008, Axel Dörfler, axeld at pinc-software.de. All rights reserved.
+ * Copyright 2005-2009, Axel Dörfler, axeld at 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 @@
 
 /*!	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 @@
 
 
 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 @@
 
 
 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 @@
 
 
 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 @@
 	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 @@
 
 
 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 @@
 
 
 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 @@
 
 
 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 @@
 
 
 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 @@
 
 
 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 @@
 
 
 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;

Modified: haiku/trunk/src/add-ons/kernel/drivers/graphics/vesa/device.cpp
===================================================================
--- haiku/trunk/src/add-ons/kernel/drivers/graphics/vesa/device.cpp	2009-06-05 12:33:22 UTC (rev 30973)
+++ haiku/trunk/src/add-ons/kernel/drivers/graphics/vesa/device.cpp	2009-06-05 13:03:05 UTC (rev 30974)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2005-2008, Axel Dörfler, axeld at pinc-software.de. All rights reserved.
+ * Copyright 2005-2009, Axel Dörfler, axeld at 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 @@
 
 
 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 @@
 
 
 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 @@
 
 		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 @@
 		}
 
 		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 @@
 
 
 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
+};

Modified: haiku/trunk/src/add-ons/kernel/drivers/graphics/vesa/vesa.cpp
===================================================================
--- haiku/trunk/src/add-ons/kernel/drivers/graphics/vesa/vesa.cpp	2009-06-05 12:33:22 UTC (rev 30973)
+++ haiku/trunk/src/add-ons/kernel/drivers/graphics/vesa/vesa.cpp	2009-06-05 13:03:05 UTC (rev 30974)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2005-2008, Axel Dörfler, axeld at pinc-software.de. All rights reserved.
+ * Copyright 2005-2009, Axel Dörfler, axeld at pinc-software.de.
  * Distributed under the terms of the MIT License.
  */
 
@@ -44,26 +44,26 @@
 
 
 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 @@
 
 
 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 @@
 }
 
 
+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 @@
 	}
 
 	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 @@
 	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 @@
 
 
 void
-vesa_uninit(vesa_info &info)
+vesa_uninit(vesa_info& info)
 {
 	dprintf(DEVICE_NAME": vesa_uninit()\n");
 
@@ -168,7 +228,7 @@
 
 
 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 @@
 		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 @@
 
 	// 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;
+}

Modified: haiku/trunk/src/add-ons/kernel/drivers/graphics/vesa/vesa_private.h
===================================================================
--- haiku/trunk/src/add-ons/kernel/drivers/graphics/vesa/vesa_private.h	2009-06-05 12:33:22 UTC (rev 30973)
+++ haiku/trunk/src/add-ons/kernel/drivers/graphics/vesa/vesa_private.h	2009-06-05 13:03:05 UTC (rev 30974)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2005-2008, Axel Dörfler, axeld at pinc-software.de. All rights reserved.
+ * Copyright 2005-2009, Axel Dörfler, axeld at pinc-software.de.
  * Distributed under the terms of the MIT License.
  */
 #ifndef VESA_PRIVATE_H
@@ -22,14 +22,17 @@
 	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 */




More information about the Haiku-commits mailing list