Exemple #1
0
static status_t
SetVesaDisplayMode(uint16 mode)
{
	// Set the VESA display mode, and return B_OK if successful.

#define SET_MODE_MASK				0x01ff
#define SET_MODE_LINEAR_BUFFER		(1 << 14)

	vm86_state vmState;

	status_t status = vm86_prepare(&vmState, 0x2000);
	if (status != B_OK) {
		TRACE("SetVesaDisplayMode(); vm86_prepare() failed, status: 0x%lx\n",
			status);
		return status;
	}

	vmState.regs.eax = 0x4f02;
	vmState.regs.ebx = (mode & SET_MODE_MASK) | SET_MODE_LINEAR_BUFFER;

	status = vm86_do_int(&vmState, 0x10);
	if (status != B_OK) {
		TRACE("SetVesaDisplayMode(0x%x): vm86_do_int failed\n", mode);
	}

	if (status == B_OK && (vmState.regs.eax & 0xffff) != 0x4f) {
		TRACE("SetVesaDisplayMode(0x%x): BIOS returned 0x%04lx\n", mode,
			vmState.regs.eax & 0xffff);
		status = B_ERROR;
	}

	vm86_cleanup(&vmState);

	return status;
}
status_t
vesa_set_indexed_colors(vesa_info& info, uint8 first, uint8* colors,
	uint16 count)
{
	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));
		return status;
	}

	uint8* palette = (uint8*)0x1000;
	uint32 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;

		// order is BGR-
		palette[i * 4 + 0] = color[2] >> shift;
		palette[i * 4 + 1] = color[1] >> shift;
		palette[i * 4 + 2] = color[0] >> shift;
		palette[i * 4 + 3] = 0;
	}

	// 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;

	status = vm86_do_int(&vmState, 0x10);
	if (status != B_OK) {
		dprintf(DEVICE_NAME ": vesa_set_indexed_colors(): vm86 failed: %s\n",
			strerror(status));
		goto out;
	}

	if ((vmState.regs.eax & 0xffff) != 0x4f) {
		dprintf(DEVICE_NAME ": vesa_set_indexed_colors(): BIOS returned "
			"0x%04lx\n", vmState.regs.eax & 0xffff);
		status = B_ERROR;
	}

out:
	vm86_cleanup(&vmState);
	return status;
}
status_t
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");
		return status;
	}

	// Get mode information
	struct vbe_mode_info 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 out;
	}

	// Set 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 out;
	}

	if (info.modes[mode].bits_per_pixel <= 8)
		vbe_set_bits_per_gun(vmState, info, 8);

	// Map new frame buffer if necessary

	status = remap_frame_buffer(info, modeInfo.physical_base, modeInfo.width,
		modeInfo.height, modeInfo.bits_per_pixel, modeInfo.bytes_per_row,
		false);
	if (status == B_OK) {
		// Update shared frame buffer information
		info.shared_info->current_mode.virtual_width = modeInfo.width;
		info.shared_info->current_mode.virtual_height = modeInfo.height;
		info.shared_info->current_mode.space = get_color_space_for_depth(
			modeInfo.bits_per_pixel);
	}

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;
}
static status_t
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));
		return status;
	}

	status = vbe_set_bits_per_gun(vmState, info, bits);

	vm86_cleanup(&vmState);
	return status;
}
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;
}
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;
}
Exemple #8
0
static status_t
GetEdidFromBIOS(edid1_raw& edidRaw)
{
	// Get the EDID info from the video BIOS, and return B_OK if successful.

#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);
	if (status != B_OK) {
		TRACE("GetEdidFromBIOS(); vm86_prepare() failed, status: 0x%lx\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;

	status = vm86_do_int(&vmState, 0x10);
	if (status == B_OK) {
		// AH contains the error code, and AL determines wether or not the
		// function is supported.
		if (vmState.regs.eax != 0x4f)
			status = B_NOT_SUPPORTED;

		// Test if DDC is supported by the monitor.
		if ((vmState.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*)0x1000;

		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);
		if (status == B_OK) {
			if (vmState.regs.eax != 0x4f) {
				status = B_NOT_SUPPORTED;
			} else {
				// Copy the EDID info to the caller's location, and compute the
				// checksum of the EDID info while copying.

				uint8 sum = 0;
				uint8 allOr = 0;
				uint8* dest = (uint8*)&edidRaw;
				uint8* src = (uint8*)edid;

				for (uint32 j = 0; j < sizeof(edidRaw); j++) {
					sum += *src;
					allOr |= *src;
					*dest++ = *src++;
				}

				if (allOr == 0) {
					TRACE("GetEdidFromBIOS(); EDID info contains only zeros\n");
					status = B_ERROR;
				} else if (sum != 0) {
					TRACE("GetEdidFromBIOS(); Checksum error in EDID info\n");
					status = B_ERROR;
				}
			}
		}
	}

	vm86_cleanup(&vmState);

	return status;
}