DevVGA.cpp revision 2be9d7aaf29390865922e4200cd20e2fb6063f6b
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * DevVGA - VBox VGA/VESA device.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Copyright (C) 2006-2011 Oracle Corporation
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * available from http://www.virtualbox.org. This file is free software;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * you can redistribute it and/or modify it under the terms of the GNU
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * General Public License (GPL) as published by the Free Software
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * --------------------------------------------------------------------
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * This code is based on:
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * QEMU VGA Emulator.
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * Copyright (c) 2003 Fabrice Bellard
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * Permission is hereby granted, free of charge, to any person obtaining a copy
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * of this software and associated documentation files (the "Software"), to deal
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * in the Software without restriction, including without limitation the rights
930b5f872e89407f445d4000d4e4aaecaa6a0998vboxsync * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * copies of the Software, and to permit persons to whom the Software is
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * furnished to do so, subject to the following conditions:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * The above copyright notice and this permission notice shall be included in
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * all copies or substantial portions of the Software.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * THE SOFTWARE.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/*******************************************************************************
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync* Defined Constants And Macros *
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync*******************************************************************************/
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/* WARNING!!! All defines that affect VGAState should be placed to DevVGA.h !!!
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * NEVER place them here as this would lead to VGAState inconsistency
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * across different .cpp files !!!
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** The size of the VGA GC mapping.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * This is supposed to be all the VGA memory accessible to the guest.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * The initial value was 256KB but NTAllInOne.iso appears to access more
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * thus the limit was upped to 512KB.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @todo Someone with some VGA knowhow should make a better guess at this value.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#define PCIDEV_2_VGASTATE(pPciDev) ((VGAState *)((uintptr_t)pPciDev - RT_OFFSETOF(VGAState, Dev)))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#endif /* VBOX_WITH_HGSMI */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** Converts a vga adaptor state pointer to a device instance pointer. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#define VGASTATE2DEVINS(pVgaState) ((pVgaState)->CTX_SUFF(pDevIns))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** Check that the video modes fit into virtual video memory.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Only works when VBE_NEW_DYN_LIST is defined! */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** Check buffer if an VRAM offset is within the right range or not. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#if defined(IN_RC) || defined(VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertMsgReturn((off) < (pThis)->vram_size, ("%RX32 !< %RX32\n", (uint32_t)(off), (pThis)->vram_size), VINF_SUCCESS); \
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync Log2(("%Rfn[%d]: %RX32 -> R3\n", __PRETTY_FUNCTION__, __LINE__, (off))); \
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync } while (0)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertMsgReturn((off) < (pThis)->vram_size, ("%RX32 !< %RX32\n", (uint32_t)(off), (pThis)->vram_size), VINF_SUCCESS)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** Check buffer if an VRAM offset is within the right range or not. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#if defined(IN_RC) || defined(VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync# define VERIFY_VRAM_READ_OFF_RETURN(pThis, off, rcVar) \
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertMsgReturn((off) < (pThis)->vram_size, ("%RX32 !< %RX32\n", (uint32_t)(off), (pThis)->vram_size), 0xff); \
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync Log2(("%Rfn[%d]: %RX32 -> R3\n", __PRETTY_FUNCTION__, __LINE__, (off))); \
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return 0; \
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync } while (0)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync# define VERIFY_VRAM_READ_OFF_RETURN(pThis, off, rcVar) \
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertMsgReturn((off) < (pThis)->vram_size, ("%RX32 !< %RX32\n", (uint32_t)(off), (pThis)->vram_size), 0xff)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/*******************************************************************************
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync* Header Files *
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync*******************************************************************************/
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#endif /* IN_RING3 */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/* should go BEFORE any other DevVGA include to make all DevVGA.h config defines be visible */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#if defined(VBE_NEW_DYN_LIST) && defined(IN_RING3) && !defined(VBOX_DEVICE_STRUCT_TESTCASE)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/*******************************************************************************
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync* Structures and Typedefs *
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync*******************************************************************************/
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** BMP File Format Bitmap Header. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsynctypedef struct
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** Pointer to a bitmap header*/
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** OS/2 1.x Information Header Format. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsynctypedef struct
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** Pointer to a OS/2 1.x header format */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** OS/2 2.0 Information Header Format. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsynctypedef struct
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync uint32_t Compression; /* Compression Scheme (0=none) */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync uint32_t XPelsPerMeter; /* Horz. Resolution in Pixels/Meter */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync uint32_t YPelsPerMeter; /* Vert. Resolution in Pixels/Meter */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync uint32_t ClrUsed; /* Number of Colors in Color Table */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync uint32_t ClrImportant; /* Number of Important Colors */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync uint16_t Reserved; /* Reserved FIelds (always 0) */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync uint16_t Rendering; /* Halftone Algorithm Used on Image */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync uint32_t ColorEncoding; /* Color Table Format (always 0) */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync uint32_t Identifier; /* Misc. Field for Application Use */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** Pointer to a OS/2 2.0 header format */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** Windows 3.x Information Header Format. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsynctypedef struct
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync uint32_t Compression; /* Compression Scheme (0=none) */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync uint32_t XPelsPerMeter; /* Horz. Resolution in Pixels/Meter */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync uint32_t YPelsPerMeter; /* Vert. Resolution in Pixels/Meter */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync uint32_t ClrUsed; /* Number of Colors in Color Table */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync uint32_t ClrImportant; /* Number of Important Colors */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** Pointer to a Windows 3.x header format */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** @name BMP compressions.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** @name BMP header sizes.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** The BIOS boot menu text position, X. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** The BIOS boot menu text position, Y. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** Width of the "Press F12 to select boot device." bitmap.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync Anything that exceeds the limit of F12BootText below is filled with
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync background. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** Height of the boot device selection bitmap, see LOGO_F12TEXT_WIDTH. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** The BIOS logo delay time (msec). */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#define LOGO_MAX_SIZE LOGO_MAX_WIDTH * LOGO_MAX_HEIGHT * 4
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/*******************************************************************************
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync* Global Variables *
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync*******************************************************************************/
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/* "Press F12 to select boot device." bitmap. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0x0F, 0x7C,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync 0xF8, 0xF0, 0x01, 0xE0, 0x81, 0x9F, 0x3F, 0x00, 0x70, 0xF8, 0x00, 0xE0, 0xC3,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync 0x07, 0x0F, 0x1F, 0x3E, 0x70, 0x00, 0xF0, 0xE1, 0xC3, 0x07, 0x0E, 0x00, 0x6E,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync 0x7C, 0x60, 0xE0, 0xE1, 0xC3, 0x07, 0xC6, 0x80, 0x81, 0x31, 0x63, 0xC6, 0x00,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync 0x30, 0x80, 0x61, 0x0C, 0x00, 0x36, 0x63, 0x00, 0x8C, 0x19, 0x83, 0x61, 0xCC,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync 0x18, 0x36, 0x00, 0xCC, 0x8C, 0x19, 0xC3, 0x06, 0xC0, 0x8C, 0x31, 0x3C, 0x30,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync 0x8C, 0x19, 0x83, 0x31, 0x60, 0x60, 0x00, 0x0C, 0x18, 0x00, 0x0C, 0x60, 0x18,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync 0x00, 0x80, 0xC1, 0x18, 0x00, 0x30, 0x06, 0x60, 0x18, 0x30, 0x80, 0x01, 0x00,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync 0x33, 0x63, 0xC6, 0x30, 0x00, 0x30, 0x63, 0x80, 0x19, 0x0C, 0x03, 0x06, 0x00,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync 0x0C, 0x18, 0x18, 0xC0, 0x81, 0x03, 0x00, 0x03, 0x18, 0x0C, 0x00, 0x60, 0x30,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync 0x06, 0x00, 0x87, 0x01, 0x18, 0x06, 0x0C, 0x60, 0x00, 0xC0, 0xCC, 0x98, 0x31,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync 0x0C, 0x00, 0xCC, 0x18, 0x30, 0x0C, 0xC3, 0x80, 0x01, 0x00, 0x03, 0x66, 0xFE,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync 0x18, 0x30, 0x00, 0xC0, 0x02, 0x06, 0x06, 0x00, 0x18, 0x8C, 0x01, 0x60, 0xE0,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync 0x0F, 0x86, 0x3F, 0x03, 0x18, 0x00, 0x30, 0x33, 0x66, 0x0C, 0x03, 0x00, 0x33,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync 0xFE, 0x0C, 0xC3, 0x30, 0xE0, 0x0F, 0xC0, 0x87, 0x9B, 0x31, 0x63, 0xC6, 0x00,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync 0xF0, 0x80, 0x01, 0x03, 0x00, 0x06, 0x63, 0x00, 0x8C, 0x19, 0x83, 0x61, 0xCC,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync 0x18, 0x06, 0x00, 0x6C, 0x8C, 0x19, 0xC3, 0x00, 0x80, 0x8D, 0x31, 0xC3, 0x30,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync 0x8C, 0x19, 0x03, 0x30, 0xB3, 0xC3, 0x87, 0x0F, 0x1F, 0x00, 0x2C, 0x60, 0x80,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync 0x01, 0xE0, 0x87, 0x0F, 0x00, 0x3E, 0x7C, 0x60, 0xF0, 0xE1, 0xE3, 0x07, 0x00,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync 0x0F, 0x3E, 0x7C, 0xFC, 0x00, 0xC0, 0xC3, 0xC7, 0x30, 0x0E, 0x3E, 0x7C, 0x00,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync 0xCC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x1E, 0xC0, 0x00, 0x60, 0x00,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x60, 0x00, 0xC0, 0x00, 0x00, 0x00,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync 0x0C, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync 0x00, 0x00, 0x00, 0xC0, 0x0C, 0x87, 0x31, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync 0x00, 0x06, 0x00, 0x00, 0x18, 0x00, 0x30, 0x00, 0x00, 0x00, 0x03, 0x00, 0x30,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xE0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync 0xF8, 0x83, 0xC1, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync 0x00, 0x04, 0x00, 0x0E, 0x00, 0x00, 0x80, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x30,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Set a VRAM page dirty.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param pThis VGA instance data.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param offVRAM The VRAM offset of the page to set.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncDECLINLINE(void) vga_set_dirty(VGAState *pThis, RTGCPHYS offVRAM)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertMsg(offVRAM < pThis->vram_size, ("offVRAM = %p, pThis->vram_size = %p\n", offVRAM, pThis->vram_size));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ASMBitSet(&pThis->au32DirtyBitmap[0], offVRAM >> PAGE_SHIFT);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Tests if a VRAM page is dirty.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @returns true if dirty.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @returns false if clean.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param pThis VGA instance data.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param offVRAM The VRAM offset of the page to check.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncDECLINLINE(bool) vga_is_dirty(VGAState *pThis, RTGCPHYS offVRAM)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertMsg(offVRAM < pThis->vram_size, ("offVRAM = %p, pThis->vram_size = %p\n", offVRAM, pThis->vram_size));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return ASMBitTest(&pThis->au32DirtyBitmap[0], offVRAM >> PAGE_SHIFT);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Reset dirty flags in a give range.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param pThis VGA instance data.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param offVRAMStart Offset into the VRAM buffer of the first page.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param offVRAMEnd Offset into the VRAM buffer of the last page - exclusive.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncDECLINLINE(void) vga_reset_dirty(VGAState *pThis, RTGCPHYS offVRAMStart, RTGCPHYS offVRAMEnd)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ASMBitClearRange(&pThis->au32DirtyBitmap[0], offVRAMStart >> PAGE_SHIFT, offVRAMEnd >> PAGE_SHIFT);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/* force some bits to zero */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#define PAT(x) (x)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#define PAT(x) (x)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#endif /* IN_RING3 */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/* Update the values needed for calculating Vertical Retrace and
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Display Enable status bits more or less accurately. The Display Enable
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * bit is set (indicating *disabled* display signal) when either the
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * horizontal (hblank) or vertical (vblank) blanking is active. The
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Vertical Retrace bit is set when vertical retrace (vsync) is active.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Unless the CRTC is horribly misprogrammed, vsync implies vblank.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync unsigned htotal_cclks, vtotal_lines, chars_per_sec;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync unsigned hblank_start_cclk, hblank_end_cclk, hblank_width, hblank_skew_cclks;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync unsigned vblank_start_line, vblank_end, vblank_width;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync const int clocks[] = {25175000, 28322000, 25175000, 25175000};
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* For horizontal timings, we only care about the blanking start/end. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync hblank_end_cclk = (s->cr[0x03] & 0x1f) + ((s->cr[0x05] & 0x80) >> 2);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* For vertical timings, we need both the blanking start/end... */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync vtotal_lines = s->cr[0x06] + ((s->cr[0x07] & 1) << 8) + ((s->cr[0x07] & 0x20) << 4) + 2;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync vblank_start_line = s->cr[0x15] + ((s->cr[0x07] & 8) << 5) + ((s->cr[0x09] & 0x20) << 4);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* ... and the vertical retrace (vsync) start/end. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync vsync_start_line = s->cr[0x10] + ((s->cr[0x07] & 4) << 6) + ((s->cr[0x07] & 0x80) << 2);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Calculate the blanking and sync widths. The way it's implemented in
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * the VGA with limited-width compare counters is quite a piece of work.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync hblank_width = (hblank_end_cclk - hblank_start_cclk) & 0x3f;/* 6 bits */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync vblank_width = (vblank_end - vblank_start_line) & 0xff; /* 8 bits */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync vsync_width = (vsync_end - vsync_start_line) & 0xf; /* 4 bits */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Calculate the dot and character clock rates. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync clock_doubled = (s->sr[0x01] >> 3) & 1; /* Clock doubling bit. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync char_dots = (s->sr[0x01] & 1) ? 8 : 9; /* 8 or 9 dots per cclk. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync Assert(chars_per_sec); /* Can't possibly be zero. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Calculate the number of cclks per entire frame. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync Assert(r->frame_cclks); /* Can't possibly be zero. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (r->v_freq_hz) { /* Could be set to emulate a specific rate. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync r->cclk_ns = 1000000000 / (r->frame_cclks * r->v_freq_hz);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Calculate timings in cclks/lines. Stored but not directly used. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync r->hb_start = hblank_start_cclk + hblank_skew_cclks;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync r->hb_end = hblank_start_cclk + hblank_width + hblank_skew_cclks;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Calculate timings in nanoseconds. For easier comparisons, the frame
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * is considered to start at the beginning of the vertical and horizontal
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * blanking period.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync r->vs_start_ns = (r->vs_start - r->vb_start) * r->h_total_ns;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync r->vs_end_ns = (r->vs_end - r->vb_start) * r->h_total_ns;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync uint8_t val = s->st01 & ~(ST01_V_RETRACE | ST01_DISP_ENABLE);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync time_ns = PDMDevHlpTMTimeVirtGetNano(VGASTATE2DEVINS(s));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Determine the time within the frame. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* See if we're in the vertical blanking period... */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* ... and additionally in the vertical sync period. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (cur_frame_ns >= r->vs_start_ns && cur_frame_ns <= r->vs_end_ns)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Determine the time within the current scanline. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* See if we're in the horizontal blanking period. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Color */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Monochrome */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncstatic uint32_t vga_ioport_read(void *opaque, uint32_t addr)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* check port range access depending on color/monochrome mode */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case 0x3c0:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (s->ar_flip_flop == 0) {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case 0x3c1:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case 0x3c2:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case 0x3c4:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case 0x3c5:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync Log2(("vga: read SR%x = 0x%02x\n", s->sr_index, val));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case 0x3c7:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case 0x3c8:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case 0x3c9:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync val = s->palette[s->dac_read_index * 3 + s->dac_sub_index];
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case 0x3ca:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case 0x3cc:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case 0x3ce:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case 0x3cf:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync Log2(("vga: read GR%x = 0x%02x\n", s->gr_index, val));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case 0x3b4:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case 0x3d4:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case 0x3b5:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case 0x3d5:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync Log2(("vga: read CR%x = 0x%02x\n", s->cr_index, val));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case 0x3ba:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case 0x3da:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync Log(("VGA: read addr=0x%04x data=0x%02x\n", addr, val));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncstatic void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync Log(("VGA: write addr=0x%04x data=0x%02x\n", addr, val));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* check port range access depending on color/monochrome mode */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case 0x3c0:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (s->ar_flip_flop == 0) {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case 0x3c2:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync s->st00 = (s->st00 & ~0x10) | (0x90 >> ((val >> 2) & 0x3));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case 0x3c4:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case 0x3c5:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync Log2(("vga: write SR%x = 0x%02x\n", s->sr_index, val));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* The VGA region is (could be) affected by this change; reset all aliases we've created. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync IOMMMIOResetRegion(PDMDevHlpGetVM(s->CTX_SUFF(pDevIns)), 0x000a0000);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case 0x3c7:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case 0x3c8:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case 0x3c9:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case 0x3ce:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case 0x3cf:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync Log2(("vga: write GR%x = 0x%02x\n", s->gr_index, val));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* The VGA region is (could be) affected by this change; reset all aliases we've created. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync IOMMMIOResetRegion(PDMDevHlpGetVM(s->CTX_SUFF(pDevIns)), 0x000a0000);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case 0x3b4:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case 0x3d4:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case 0x3b5:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case 0x3d5:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync Log2(("vga: write CR%x = 0x%02x\n", s->cr_index, val));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* handle CR0-7 protection */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* can always write bit 4 of CR7 */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* The following registers are only updated during a mode set. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync switch(s->cr_index) {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case 0x3ba:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync case 0x3da:
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncstatic uint32_t vbe_ioport_read_index(void *opaque, uint32_t addr)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncstatic uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_GETCAPS) {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* XXX: do not hardcode ? */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Reading from the port means that the old additions are requesting the number of monitors. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync Log(("VBE: read index=0x%x val=0x%x\n", s->vbe_index, val));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#define VBE_PITCH_ALIGN 4 /* Align pitch to 32 bits - Qt requires that. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/* Calculate scanline pitch based on bit depth and width in pixels. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncstatic uint32_t calc_line_pitch(uint16_t bpp, uint16_t width)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Align the pitch to some sensible value. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync aligned_pitch = (pitch + (VBE_PITCH_ALIGN - 1)) & ~(VBE_PITCH_ALIGN - 1);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync Log(("VBE: Line pitch %d aligned to %d bytes\n", pitch, aligned_pitch));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/* Calculate line width in pixels based on bit depth and pitch. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncstatic uint32_t calc_line_width(uint16_t bpp, uint32_t pitch)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncstatic void recaltulate_data(VGAState *s, bool fVirtHeightOnly)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync uint16_t cVirtWidth = s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH];
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return; /* Not enough data has been set yet. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync uint32_t cbLinePitch = calc_line_pitch(cBPP, cVirtWidth);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync uint16_t offX = s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET];
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync uint16_t offY = s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET];
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync s->vbe_line_offset = RT_MIN(cbLinePitch, s->vram_size);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync s->vbe_start_addr = RT_MIN(offStart, s->vram_size);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* The VBE_DISPI_INDEX_VIRT_HEIGHT is used to prevent setting resolution bigger than VRAM permits
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * it is used instead of VBE_DISPI_INDEX_YRES *only* in case
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] < s->vbe_regs[VBE_DISPI_INDEX_YRES]
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * We can not simply do s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = cVirtHeight since
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * the cVirtHeight we calculated can exceed the 16bit value range
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * instead we'll check if it's bigger than s->vbe_regs[VBE_DISPI_INDEX_YRES], and if yes,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * assign the s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] with a dummy UINT16_MAX value
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * that is always bigger than s->vbe_regs[VBE_DISPI_INDEX_YRES]
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * to just ensure the s->vbe_regs[VBE_DISPI_INDEX_YRES] is always used */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = (cVirtHeight >= (uint32_t)s->vbe_regs[VBE_DISPI_INDEX_YRES]) ? UINT16_MAX : (uint16_t)cVirtHeight;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncstatic void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncstatic int vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync bool fRecalculate = false;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync Log(("VBE: write index=0x%x val=0x%x\n", s->vbe_index, val));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#endif /* VBOX_WITH_HGSMI */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync max_bank = s->vbe_bank_max >> 2; /* Each bank really covers 256K */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Old software may pass garbage in the high byte of bank. If the maximum
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * bank fits into a single byte, toss the high byte the user supplied.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* The VGA region is (could be) affected by this change; reset all aliases we've created. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync IOMMMIOResetRegion(PDMDevHlpGetVM(s->CTX_SUFF(pDevIns)), 0x000a0000);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync !(s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED)) {
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Check the values before we screw up with a resolution which is too big or small. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync cb = s->vbe_regs[VBE_DISPI_INDEX_XRES] * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync uint16_t cVirtWidth = s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH];
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertMsgFailed(("VIRT WIDTH=%d YRES=%d cb=%d vram_size=%d\n",
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH], s->vbe_regs[VBE_DISPI_INDEX_YRES], cb, s->vram_size));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return VINF_SUCCESS; /* Note: silent failure like before */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* When VBE interface is enabled, it is reset. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* clear the screen (should be done in BIOS) */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync uint16_t cY = RT_MIN(s->vbe_regs[VBE_DISPI_INDEX_YRES],
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* we initialize the VGA graphic mode (should be done
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync in BIOS) */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync s->gr[0x06] = (s->gr[0x06] & ~0x0c) | 0x05; /* graphic mode + memory map 1 */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* width */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* height (only meaningful if < 1024) */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* line compare to 1023 */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync s->gr[0x05] = (s->gr[0x05] & ~0x60) | (shift_control << 5);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* sunlover 30.05.2007
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * The ar_index remains with bit 0x20 cleared after a switch from fullscreen
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * DOS mode on Windows XP guest. That leads to GMODE_BLANK in vga_update_display.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * But the VBE mode is graphics, so not a blank anymore.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* XXX: the bios should do that */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* sunlover 21.12.2006
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Here is probably more to reset. When this was executed in GC
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * then the *update* functions could not detect a mode change.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Or may be these update function should take the s->vbe_regs[s->vbe_index]
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * into account when detecting a mode change.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * The 'mode reset not detected' problem is now fixed by executing the
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * VBE_DISPI_INDEX_ENABLE case always in RING3 in order to call the
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * LFBChange callback.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * LFB video mode is either disabled or changed. This notification
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * is used by the display to disable VBVA.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync s->pDrv->pfnLFBModeChange(s->pDrv, (val & VBE_DISPI_ENABLED) != 0);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* The VGA region is (could be) affected by this change; reset all aliases we've created. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync IOMMMIOResetRegion(PDMDevHlpGetVM(s->CTX_SUFF(pDevIns)), 0x000a0000);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#endif /* IN_RING3 */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Changes in the VGA device are minimal. The device is bypassed. The driver does all work. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync else if (val == VBOX_VIDEO_INTERPRET_ADAPTER_MEMORY)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync s->pDrv->pfnProcessAdapterData(s->pDrv, s->CTX_SUFF(vram_ptr), s->vram_size);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync else if ((val & 0xFFFF0000) == VBOX_VIDEO_INTERPRET_DISPLAY_MEMORY_BASE)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync s->pDrv->pfnProcessDisplayData(s->pDrv, s->CTX_SUFF(vram_ptr), val & 0xFFFF);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#endif /* IN_RING3 */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/* called for accesses between 0xa0000 and 0xc0000 */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncstatic uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr, int *prc)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* convert to VGA memory offset */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RTGCPHYS GCPhys = addr; /* save original address */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return 0xff;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return 0xff;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return 0xff;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* chain 4 mode : simplest access */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* If all planes are accessible, then map the page to the frame buffer and make it writable. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** @todo only allow read access (doesn't work now) */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync IOMMMIOMapMMIO2Page(PDMDevHlpGetVM(s->CTX_SUFF(pDevIns)), GCPhys, s->GCPhysVRAM + addr, X86_PTE_RW|X86_PTE_P);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Set as dirty as write accesses won't be noticed now. */
return ret;
#ifndef IN_RC
switch(memory_map_mode) {
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
# ifndef IN_RC
IOMMMIOMapMMIO2Page(PDMDevHlpGetVM(s->CTX_SUFF(pDevIns)), GCPhys, s->GCPhysVRAM + addr, X86_PTE_RW | X86_PTE_P);
s->fRemappedVGA = true;
#ifdef IN_RING0
s->u64LastLatchedAccess = 0;
return VINF_EM_RAW_EMULATE_IO_BLOCK;
if (s->u64LastLatchedAccess)
Log2(("Reset mask (was %d) delta %RX64 (limit %x)\n", s->iMask, u64CurTime - s->u64LastLatchedAccess, s_aDelta[s->iMask]));
if (s->iMask)
s->iMask--;
s->u64LastLatchedAccess = 0;
s->iMask = 0;
s->cLatchAccesses = 0;
switch(write_mode) {
goto do_write;
switch(func_select) {
return VINF_SUCCESS;
#if defined(IN_RING3)
int dscan);
static inline unsigned int rgb_to_pixel8(unsigned int r, unsigned int g, unsigned b)
static inline unsigned int rgb_to_pixel15(unsigned int r, unsigned int g, unsigned b)
static inline unsigned int rgb_to_pixel16(unsigned int r, unsigned int g, unsigned b)
static inline unsigned int rgb_to_pixel32(unsigned int r, unsigned int g, unsigned b)
#include "DevVGATmpl.h"
#include "DevVGATmpl.h"
#include "DevVGATmpl.h"
#include "DevVGATmpl.h"
static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
unsigned int col;
return col;
static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b)
unsigned int col;
return col;
static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b)
unsigned int col;
return col;
static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
unsigned int col;
return col;
bool full_update = false;
v = s->ar[i];
full_update = true;
return full_update;
bool full_update = false;
int wide_dac;
if (wide_dac)
full_update = true;
return full_update;
#ifdef CONFIG_BOCHS_VBE
bool full_update = false;
full_update = true;
return full_update;
switch(depth) {
full_update = true;
full_update = true;
s->plane_updated = 0;
full_update = true;
s1 = s->CTX_SUFF(vram_ptr) + (s->start_addr * 8); /** @todo r=bird: Add comment why we do *8 instead of *4, it's not so obvious... */
return VINF_SUCCESS;
if (fFailOnResize)
return VERR_TRY_AGAIN;
full_update = true;
return rc;
if (reset_dirty)
#ifdef WORDS_BIGENDIAN
dup9 = 0;
ch_attr_ptr++;
} else if (cy_start >= 0) {
if (cy_start >= 0)
return VINF_SUCCESS;
int ret;
#ifdef CONFIG_BOCHS_VBE
ret = 0;
return ret;
#ifdef CONFIG_BOCHS_VBE
int rc;
* although we should avoid calling pfnResize for XPDM as well, since pfnResize is actually an extra resize
rc = s->pDrv->pfnResize(s->pDrv, cBits, s->CTX_SUFF(vram_ptr) + s->start_addr * 4, s->line_offset, cx, cy);
return VERR_TRY_AGAIN;
return rc;
if (s->shift_control == 0)
update_palette16(s);
update_palette16(s);
return VINF_SUCCESS;
uint8_t *d;
full_update = true;
if (shift_control == 0) {
v = VGA_DRAW_LINE4D2;
v = VGA_DRAW_LINE4;
v = VGA_DRAW_LINE2D2;
v = VGA_DRAW_LINE2;
switch(s->get_bpp(s)) {
v = VGA_DRAW_LINE8D2;
v = VGA_DRAW_LINE8;
v = VGA_DRAW_LINE15;
v = VGA_DRAW_LINE16;
v = VGA_DRAW_LINE24;
v = VGA_DRAW_LINE32;
if (fFailOnResize)
return VERR_TRY_AGAIN;
if (rc != VINF_SUCCESS) /* Return any rc, particularly VINF_VGA_RESIZE_IN_PROGRESS, to the caller. */
return rc;
full_update = true;
if (s->cursor_invalidate)
s->cursor_invalidate(s);
y1 = 0;
for(y = 0; y < height; y++) {
if (update) {
if (y_start < 0)
y_start = y;
if (s->fRenderVRAM)
if (s->cursor_draw_line)
s->cursor_draw_line(s, d, y);
if (y_start >= 0) {
if (!multi_run) {
y1++;
if (y2 == 0) {
--y2;
multi_run--;
addr1 = 0;
d += linesize;
if (y_start >= 0) {
return VINF_SUCCESS;
int i, w, val;
uint8_t *d;
if (!full_update)
val = 0;
for(i = 0; i < (int)s->last_scr_height; i++) {
d += cbScanline;
static DECLCALLBACK(void) voidUpdateRect(PPDMIDISPLAYCONNECTOR pInterface, uint32_t x, uint32_t y, uint32_t cx, uint32_t cy)
#define GMODE_TEXT 0
int graphic_mode;
if (fUpdateAll) {
typedef DECLCALLBACK(void) FNUPDATERECT(PPDMIDISPLAYCONNECTOR pInterface, uint32_t x, uint32_t y, uint32_t cx, uint32_t cy);
int fBlank = 0;
if (fBlank) {
if (s->pDrv) {
if (fBlank) {
if (s->pDrv) {
return rc;
if (full_update) {
switch(graphic_mode) {
case GMODE_TEXT:
case GMODE_GRAPH:
case GMODE_BLANK:
return rc;
#ifdef CONFIG_BOCHS_VBE
for(i = 0; i < VBE_DISPI_INDEX_NB_SAVED; i++)
qemu_put_byte(f, 0);
int is_vbe, i;
#ifdef CONFIG_BOCHS_VBE
if (!is_vbe)
for(i = 0; i < VBE_DISPI_INDEX_NB_SAVED; i++)
recaltulate_data(s, false); /* <- re-calculate the s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] since it might be invalid */
if (is_vbe)
static void vga_init_expand(void)
expand4[i] = v;
expand2[i] = v;
expand4to8[i] = v;
PDMBOTHCBDECL(int) vgaIOPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
return rc;
return VINF_SUCCESS;
PDMBOTHCBDECL(int) vgaIOPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
return rc;
return rc;
PDMBOTHCBDECL(int) vgaIOPortWriteVBEData(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
return rc;
#ifndef IN_RING3
return VINF_IOM_HC_IOPORT_WRITE;
#ifdef VBE_BYTEWISE_IO
if (!s->fWriteVBEData)
s->fWriteVBEData = false;
return rc;
s->fWriteVBEData = true;
return VINF_SUCCESS;
s->fWriteVBEData = false;
// Log(("vgaIOPortWriteVBEData: VBE_DISPI_INDEX_ENABLE & VBE_DISPI_ENABLED - Switching to host...\n"));
return rc;
return VINF_SUCCESS;
PDMBOTHCBDECL(int) vgaIOPortWriteVBEIndex(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
return rc;
#ifdef VBE_BYTEWISE_IO
if (!s->fWriteVBEIndex)
s->fWriteVBEIndex = true;
return VINF_SUCCESS;
s->fWriteVBEIndex = false;
return VINF_SUCCESS;
return VINF_SUCCESS;
PDMBOTHCBDECL(int) vgaIOPortReadVBEData(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
return rc;
#ifdef VBE_BYTEWISE_IO
if (!s->fReadVBEData)
s->fReadVBEData = true;
return VINF_SUCCESS;
s->fReadVBEData = false;
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
return VERR_IOM_IOPORT_UNUSED;
PDMBOTHCBDECL(int) vgaIOPortReadVBEIndex(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
return rc;
#ifdef VBE_BYTEWISE_IO
if (!s->fReadVBEIndex)
s->fReadVBEIndex = true;
return VINF_SUCCESS;
s->fReadVBEIndex = false;
return VINF_SUCCESS;
return VINF_SUCCESS;
return VERR_IOM_IOPORT_UNUSED;
#ifdef VBOX_WITH_HGSMI
#ifdef IN_RING3
static DECLCALLBACK(int) vgaR3IOPortHGSMIWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
return rc;
switch (Port)
#ifdef DEBUG_sunlover
#ifdef DEBUG_sunlover
return VINF_SUCCESS;
static DECLCALLBACK(int) vgaR3IOPortHGSMIRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
return rc;
switch (Port)
#ifdef DEBUG_sunlover
#ifdef DEBUG_sunlover
return rc;
* Legacy VGA memory (0xa0000 - 0xbffff) write hook, to be called from IOM and from the inside of VGADeviceGC.cpp.
static int vgaInternalMMIOFill(PVGASTATE pThis, void *pvUser, RTGCPHYS GCPhysAddr, uint32_t u32Item, unsigned cbItem, unsigned cItems)
uint32_t b;
for (i = 0; i < cbItem; i++)
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
while (cItems-- > 0)
for (i = 0; i < cbItem; i++)
GCPhysAddr++;
while (cItems-- > 0)
for (i = 0; i < cbItem; i++)
GCPhysAddr++;
for (i = 0; i < cbItem; i++)
for (i = 0; i < cbItem; i++)
for (i = 0; i < cbItem; i++)
for (i = 0; i < cbItem; i++)
while (cItems-- > 0)
((uint32_t *)pThis->CTX_SUFF(vram_ptr))[GCPhysAddr] = (((uint32_t *)pThis->CTX_SUFF(vram_ptr))[GCPhysAddr] & ~write_mask) | (aVal[0] & write_mask);
GCPhysAddr++;
while (cItems-- > 0)
((uint32_t *)pThis->CTX_SUFF(vram_ptr))[GCPhysAddr] = (((uint32_t *)pThis->CTX_SUFF(vram_ptr))[GCPhysAddr] & ~write_mask) | (aVal[0] & write_mask);
GCPhysAddr++;
((uint32_t *)pThis->CTX_SUFF(vram_ptr))[GCPhysAddr] = (((uint32_t *)pThis->CTX_SUFF(vram_ptr))[GCPhysAddr] & ~write_mask) | (aVal[1] & write_mask);
GCPhysAddr++;
while (cItems-- > 0)
for (i = 0; i < cbItem; i++)
((uint32_t *)pThis->CTX_SUFF(vram_ptr))[GCPhysAddr] = (((uint32_t *)pThis->CTX_SUFF(vram_ptr))[GCPhysAddr] & ~write_mask) | (aVal[i] & write_mask);
GCPhysAddr++;
return VINF_SUCCESS;
* Legacy VGA memory (0xa0000 - 0xbffff) write hook, to be called from IOM and from the inside of VGADeviceGC.cpp.
PDMBOTHCBDECL(int) vgaMMIOFill(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, uint32_t u32Item, unsigned cbItem, unsigned cItems)
return rc;
return rc;
PDMBOTHCBDECL(int) vgaMMIORead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
return rc;
switch (cb)
while (cb-- > 0)
return rc;
PDMBOTHCBDECL(int) vgaMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb)
return rc;
switch (cb)
return rc;
return rc;
#ifndef IN_RING3
/* In the SMP case the page table might be removed while we wait for the PGM lock in the trap handler. */
rc);
return VINF_SUCCESS;
return rc;
#ifdef IN_RC
PDMBOTHCBDECL(int) vgaGCLFBAccessHandler(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, RTGCPHYS GCPhysFault, void *pvUser)
PDMBOTHCBDECL(int) vgaR0LFBAccessHandler(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, RTGCPHYS GCPhysFault, void *pvUser)
static DECLCALLBACK(int) vgaR3LFBAccessHandler(PVM pVM, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf, PGMACCESSTYPE enmAccessType, void *pvUser)
int rc;
return VINF_PGM_HANDLER_DO_DEFAULT;
return rc;
PDMBOTHCBDECL(int) vgaIOPortReadBIOS(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
return VERR_IOM_IOPORT_UNUSED;
PDMBOTHCBDECL(int) vgaIOPortWriteBIOS(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
return rc;
switch (u32)
if (lastWasNotNewline == 0)
lastWasNotNewline = 0;
return VINF_SUCCESS;
return VERR_IOM_IOPORT_UNUSED;
#ifdef IN_RING3
# ifdef VBE_NEW_DYN_LIST
PDMBOTHCBDECL(int) vbeIOPortWriteVBEExtra(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
return rc;
return VINF_SUCCESS;
PDMBOTHCBDECL(int) vbeIOPortReadVBEExtra(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
return rc;
*pu32 = 0;
Log(("vbeIOPortReadVBEExtra: Requested address is out of VBE data!!! Address=%#x(%d) cbVBEExtraData=%#x(%d)\n",
pThis->u16VBEExtraAddress, pThis->u16VBEExtraAddress, pThis->cbVBEExtraData, pThis->cbVBEExtraData));
return rc;
uint16_t i;
case BMP_HEADER_OS21:
case BMP_HEADER_OS22:
case BMP_HEADER_WIN3:
return VERR_INVALID_PARAMETER;
return VERR_INVALID_PARAMETER;
return VERR_INVALID_PARAMETER;
return VERR_INVALID_PARAMETER;
return VERR_INVALID_PARAMETER;
const uint8_t *pu8Pal = pThis->pu8Logo + sizeof(LOGOHDR) + sizeof(BMPINFO) + pWinHdr->Size; /* ASSUMES Size location (safe) */
uint16_t j;
u32Pal |= b;
return VINF_SUCCESS;
static void vbeShowBitmap(uint16_t cBits, uint16_t xLogo, uint16_t yLogo, uint16_t cxLogo, uint16_t cyLogo, uint8_t iStep,
uint16_t i;
switch (cBits)
cbPadBytes = 0;
cbPadBytes = 0;
uint8_t j = 0, c = 0;
while (cyLeft-- > 0)
for (i = 0; i < cxLogo; i++)
switch (cBits)
c = *pu8Src++;
if (pix)
*pu8TmpPtr++;
c = *pu8Src++;
*pu8TmpPtr++;
*pu8TmpPtr++;
*pu8TmpPtr++;
PDMBOTHCBDECL(int) vbeIOPortWriteCMDLogo(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
case LOGO_CMD_SET_OFFSET:
case LOGO_CMD_SHOW_BMP:
for (int i = 0; i < LOGO_MAX_WIDTH; i++)
for (int j = 0; j < LOGO_MAX_HEIGHT; j++)
*pu32TmpPtr++ = 0;
for (int i = 0; i < LOGO_MAX_WIDTH; i++)
for (int j = 0; j < LOGO_MAX_HEIGHT; j++)
return VINF_SUCCESS;
return VINF_SUCCESS;
PDMBOTHCBDECL(int) vbeIOPortReadCMDLogo(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
PRTUINT64U p;
Log(("vbeIOPortReadCMDLogo: Requested address is out of Logo data!!! offLogoData=%#x(%d) cbLogo=%#x(%d)\n",
return VINF_SUCCESS;
switch (cb)
default: AssertFailed(); break;
Log(("vbeIOPortReadCMDLogo: LogoOffset=%#x(%d) cb=%#x %.*Rhxs\n", pThis->offLogoData, pThis->offLogoData, cb, cb, pu32));
return VINF_SUCCESS;
h = val;
if (!is_graph)
if (s->fRealRetrace)
if (pszTitle)
cCols = 0;
while (cchLeft-- > 0)
while (cCols-- > 0)
if (iRow == 0)
bool fAll = true;
fAll = true;
fAll = false;
if (pbSrc)
if (!cbLine)
if (fAll) {
return NULL;
static DECLCALLBACK(int) vgaDummyResize(PPDMIDISPLAYCONNECTOR pInterface, uint32_t bpp, void *pvVRAM, uint32_t cbLine, uint32_t cx, uint32_t cy)
return VINF_SUCCESS;
static DECLCALLBACK(void) vgaDummyUpdateRect(PPDMIDISPLAYCONNECTOR pInterface, uint32_t x, uint32_t y, uint32_t cx, uint32_t cy)
#define IDISPLAYPORT_2_VGASTATE(pInterface) ( (PVGASTATE)((uintptr_t)pInterface - RT_OFFSETOF(VGASTATE, IPort)) )
#ifndef VBOX_WITH_HGSMI
return VINF_SUCCESS;
return rc;
return VINF_SUCCESS;
#ifdef DEBUG_sunlover
return rc;
static DECLCALLBACK(int) vgaPortSetRefreshRate(PPDMIDISPLAYPORT pInterface, uint32_t cMilliesInterval)
if (cMilliesInterval)
if (!pcBits)
return VERR_INVALID_PARAMETER;
return VINF_SUCCESS;
static DECLCALLBACK(int) vgaPortTakeScreenshot(PPDMIDISPLAYPORT pInterface, uint8_t **ppu8Data, size_t *pcbData, uint32_t *pcx, uint32_t *pcy)
LogFlow(("vgaPortTakeScreenshot: ppu8Data=%p pcbData=%p pcx=%p pcy=%p\n", ppu8Data, pcbData, pcx, pcy));
return VERR_INVALID_PARAMETER;
LogFlow(("vgaPortTakeScreenshot: returns %Rrc (cbData=%d cx=%d cy=%d)\n", rc, *pcbData, *pcx, *pcy));
return rc;
static DECLCALLBACK(int) vgaPortDisplayBlt(PPDMIDISPLAYPORT pInterface, const void *pvData, uint32_t x, uint32_t y, uint32_t cx, uint32_t cy)
if ( pvData
vga_draw_line_func *pfnVgaDrawLine = vga_draw_line_table[VGA_DRAW_LINE32 * 4 + get_depth_index(pThis->pDrv->cBits)];
while (cyLeft-- > 0)
return rc;
static DECLCALLBACK(void) vgaPortUpdateDisplayRect (PPDMIDISPLAYPORT pInterface, int32_t x, int32_t y, uint32_t w, uint32_t h)
uint32_t v;
#ifdef DEBUG_sunlover
if (!s->fRenderVRAM)
#ifdef DEBUG_sunlover
#ifdef DEBUG_sunlover
#ifdef DEBUG_sunlover
switch(s->get_bpp(s))
v = VGA_DRAW_LINE8;
v = VGA_DRAW_LINE15;
v = VGA_DRAW_LINE16;
v = VGA_DRAW_LINE24;
v = VGA_DRAW_LINE32;
#ifdef DEBUG_sunlover
LogFlow(("vgaPortUpdateDisplayRect: dst: %p, %d, %d. src: %p, %d, %d\n", pu8Dst, cbLineDst, cbPixelDst, pu8Src, cbLineSrc, cbPixelSrc));
#ifdef DEBUG_sunlover
uint32_t w,
uint32_t h,
uint32_t v;
#ifdef DEBUG_sunlover
if (xSrcCorrected < 0)
xSrcCorrected = 0;
if (ySrcCorrected < 0)
ySrcCorrected = 0;
#ifdef DEBUG_sunlover
LogFlow(("vgaPortCopyRect: %d,%d %dx%d (corrected coords)\n", xSrcCorrected, ySrcCorrected, wCorrected, hCorrected));
#ifdef DEBUG_sunlover
return VINF_SUCCESS;
if ( xDst < 0
|| yDst < 0
return VERR_INVALID_PARAMETER;
switch(u32SrcBitsPerPixel)
return VINF_SUCCESS;
v = VGA_DRAW_LINE8;
v = VGA_DRAW_LINE15;
v = VGA_DRAW_LINE16;
v = VGA_DRAW_LINE24;
v = VGA_DRAW_LINE32;
#ifdef DEBUG_sunlover
LogFlow(("vgaPortCopyRect: dst: %p, %d, %d. src: %p, %d, %d\n", pu8DstPtr, cbLineDst, cbPixelDst, pu8SrcPtr, cbLineSrc, cbPixelSrc));
while (hCorrected-- > 0)
#ifdef DEBUG_sunlover
return VINF_SUCCESS;
static DECLCALLBACK(int) vgaR3IORegionMap(PPCIDEVICE pPciDev, /*unsigned*/ int iRegion, RTGCPHYS GCPhysAddress, uint32_t cb, PCIADDRESSSPACE enmType)
int rc;
LogFlow(("vgaR3IORegionMap: iRegion=%d GCPhysAddress=%RGp cb=%#x enmType=%d\n", iRegion, GCPhysAddress, cb, enmType));
return rc;
return VINF_SSM_DONT_CALL_AGAIN;
#ifdef VBOX_WITH_VIDEOHWACCEL
return VINF_SUCCESS;
#ifdef VBOX_WITH_VIDEOHWACCEL
return VINF_SUCCESS;
#ifdef VBOX_WITH_VDMA
#ifdef VBOX_WITH_HGSMI
# ifdef VBOX_WITH_VDMA
return rc;
return VINF_SUCCESS;
static DECLCALLBACK(int) vgaR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
int rc;
return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("VRAM size changed: config=%#x state=%#x"), pThis->vram_size, cbVRam);
return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Monitor count changed: config=%u state=%u"), pThis->cMonitors, cMonitors);
return rc;
if (fWithHgsmi)
#ifdef VBOX_WITH_HGSMI
return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("HGSMI is not compiled in, but it is present in the saved state"));
return VINF_SUCCESS;
#ifdef VBOX_WITH_HGSMI
return VINF_SUCCESS;
char *pchStart;
char *pchEnd;
#ifdef VBOX_WITH_HGSMI
#ifdef CONFIG_BOCHS_VBE
if (offDelta)
switch (iLUN)
#ifdef VBOX_WITH_VIDEOHWACCEL
Log(("%s/%d: warning: no driver attached to LUN #0!\n", pDevIns->pReg->szName, pDevIns->iInstance));
return rc;
return VERR_PDM_NO_SUCH_LUN;
switch (iLUN)
#ifdef VBE_NEW_DYN_LIST
#ifdef VBOX_WITH_VDMA
return VINF_SUCCESS;
int maxPage;
int bpl;
static bool s_fExpandDone = false;
int rc;
#ifdef VBE_NEW_DYN_LIST
unsigned cb;
if (!s_fExpandDone)
s_fExpandDone = true;
if (pThis->vram_size & (_256K - 1)) /* Make sure there are no partial banks even in planar modes. */
Log(("VGA: VRamSize=%#x fGCenabled=%RTbool fR0Enabled=%RTbool\n", pThis->vram_size, pThis->fGCEnabled, pThis->fR0Enabled));
#if defined(VBOX_WITH_HGSMI) && (defined(VBOX_WITH_VIDEOHWACCEL) || defined(VBOX_WITH_VDMA) || defined(VBOX_WITH_WDDM))
rc = PDMR3LdrGetSymbolRCLazy(pVM, pDevIns->pReg->szRCMod, NULL, "vgaGCLFBAccessHandler", &pThis->RCPtrLFBHandler);
AssertReleaseMsgFailed(("PDMR3LdrGetSymbolRC(, %s, \"vgaGCLFBAccessHandler\",) -> %Rrc\n", pDevIns->pReg->szRCMod, rc));
return rc;
#if defined(VBOX_WITH_HGSMI)
# if defined(VBOX_WITH_VIDEOHWACCEL)
#if defined(VBOX_WITH_CRHGSMI)
rc = PDMDevHlpMMIO2Register(pDevIns, 0 /* iRegion */, pThis->vram_size, 0, (void **)&pThis->vram_ptrR3, "VRam");
pThis->vram_ptrR0 = (RTR0PTR)pThis->vram_ptrR3; /** @todo #1865 Map parts into R0 or just use PGM access (Mac only). */
rc = PDMDevHlpMMHyperMapMMIO2(pDevIns, 0 /* iRegion */, 0 /* off */, VGA_MAPPING_SIZE, "VGA VRam", &pRCMapping);
AssertLogRelMsgRCReturn(rc, ("PDMDevHlpMMHyperMapMMIO2(%#x,) -> %Rrc\n", VGA_MAPPING_SIZE, rc), rc);
#if defined(VBOX_WITH_2X_4GB_ADDR_SPACE)
rc = PDMDevHlpMMIO2MapKernel(pDevIns, 0 /* iRegion */, 0 /* off */, VGA_MAPPING_SIZE, "VGA VRam", &pR0Mapping);
rc = PDMDevHlpIOPortRegister(pDevIns, 0x3c0, 16, NULL, vgaIOPortWrite, vgaIOPortRead, NULL, NULL, "VGA - 3c0");
return rc;
rc = PDMDevHlpIOPortRegister(pDevIns, 0x3b4, 2, NULL, vgaIOPortWrite, vgaIOPortRead, NULL, NULL, "VGA - 3b4");
return rc;
rc = PDMDevHlpIOPortRegister(pDevIns, 0x3ba, 1, NULL, vgaIOPortWrite, vgaIOPortRead, NULL, NULL, "VGA - 3ba");
return rc;
rc = PDMDevHlpIOPortRegister(pDevIns, 0x3d4, 2, NULL, vgaIOPortWrite, vgaIOPortRead, NULL, NULL, "VGA - 3d4");
return rc;
rc = PDMDevHlpIOPortRegister(pDevIns, 0x3da, 1, NULL, vgaIOPortWrite, vgaIOPortRead, NULL, NULL, "VGA - 3da");
return rc;
#ifdef VBOX_WITH_HGSMI
rc = PDMDevHlpIOPortRegister(pDevIns, VGA_PORT_HGSMI_HOST, 4, NULL, vgaR3IOPortHGSMIWrite, vgaR3IOPortHGSMIRead, NULL, NULL, "VGA - 3b0 (HGSMI host)");
return rc;
rc = PDMDevHlpIOPortRegister(pDevIns, VGA_PORT_HGSMI_GUEST, 4, NULL, vgaR3IOPortHGSMIWrite, vgaR3IOPortHGSMIRead, NULL, NULL, "VGA - 3d0 (HGSMI guest)");
return rc;
#ifdef CONFIG_BOCHS_VBE
rc = PDMDevHlpIOPortRegister(pDevIns, 0x1ce, 1, NULL, vgaIOPortWriteVBEIndex, vgaIOPortReadVBEIndex, NULL, NULL, "VGA/VBE - Index");
return rc;
rc = PDMDevHlpIOPortRegister(pDevIns, 0x1cf, 1, NULL, vgaIOPortWriteVBEData, vgaIOPortReadVBEData, NULL, NULL, "VGA/VBE - Data");
return rc;
rc = PDMDevHlpIOPortRegisterRC(pDevIns, 0x3c0, 16, 0, "vgaIOPortWrite", "vgaIOPortRead", NULL, NULL, "VGA - 3c0 (GC)");
return rc;
rc = PDMDevHlpIOPortRegisterRC(pDevIns, 0x3b4, 2, 0, "vgaIOPortWrite", "vgaIOPortRead", NULL, NULL, "VGA - 3b4 (GC)");
return rc;
rc = PDMDevHlpIOPortRegisterRC(pDevIns, 0x3ba, 1, 0, "vgaIOPortWrite", "vgaIOPortRead", NULL, NULL, "VGA - 3ba (GC)");
return rc;
rc = PDMDevHlpIOPortRegisterRC(pDevIns, 0x3d4, 2, 0, "vgaIOPortWrite", "vgaIOPortRead", NULL, NULL, "VGA - 3d4 (GC)");
return rc;
rc = PDMDevHlpIOPortRegisterRC(pDevIns, 0x3da, 1, 0, "vgaIOPortWrite", "vgaIOPortRead", NULL, NULL, "VGA - 3da (GC)");
return rc;
#ifdef CONFIG_BOCHS_VBE
rc = PDMDevHlpIOPortRegisterRC(pDevIns, 0x1ce, 1, 0, "vgaIOPortWriteVBEIndex", "vgaIOPortReadVBEIndex", NULL, NULL, "VGA/VBE - Index (GC)");
return rc;
rc = PDMDevHlpIOPortRegisterRC(pDevIns, 0x1cf, 1, 0, "vgaIOPortWriteVBEData", "vgaIOPortReadVBEData", NULL, NULL, "VGA/VBE - Data (GC)");
return rc;
rc = PDMDevHlpIOPortRegisterR0(pDevIns, 0x3c0, 16, 0, "vgaIOPortWrite", "vgaIOPortRead", NULL, NULL, "VGA - 3c0 (GC)");
return rc;
rc = PDMDevHlpIOPortRegisterR0(pDevIns, 0x3b4, 2, 0, "vgaIOPortWrite", "vgaIOPortRead", NULL, NULL, "VGA - 3b4 (GC)");
return rc;
rc = PDMDevHlpIOPortRegisterR0(pDevIns, 0x3ba, 1, 0, "vgaIOPortWrite", "vgaIOPortRead", NULL, NULL, "VGA - 3ba (GC)");
return rc;
rc = PDMDevHlpIOPortRegisterR0(pDevIns, 0x3d4, 2, 0, "vgaIOPortWrite", "vgaIOPortRead", NULL, NULL, "VGA - 3d4 (GC)");
return rc;
rc = PDMDevHlpIOPortRegisterR0(pDevIns, 0x3da, 1, 0, "vgaIOPortWrite", "vgaIOPortRead", NULL, NULL, "VGA - 3da (GC)");
return rc;
#ifdef CONFIG_BOCHS_VBE
rc = PDMDevHlpIOPortRegisterR0(pDevIns, 0x1ce, 1, 0, "vgaIOPortWriteVBEIndex", "vgaIOPortReadVBEIndex", NULL, NULL, "VGA/VBE - Index (GC)");
return rc;
rc = PDMDevHlpIOPortRegisterR0(pDevIns, 0x1cf, 1, 0, "vgaIOPortWriteVBEData", "vgaIOPortReadVBEData", NULL, NULL, "VGA/VBE - Data (GC)");
return rc;
rc = PDMDevHlpMMIORegister(pDevIns, 0x000a0000, 0x00020000, 0, vgaMMIOWrite, vgaMMIORead, vgaMMIOFill, "VGA - VGA Video Buffer");
return rc;
rc = PDMDevHlpMMIORegisterRC(pDevIns, 0x000a0000, 0x00020000, 0, "vgaMMIOWrite", "vgaMMIORead", "vgaMMIOFill");
return rc;
rc = PDMDevHlpMMIORegisterR0(pDevIns, 0x000a0000, 0x00020000, 0, "vgaMMIOWrite", "vgaMMIORead", "vgaMMIOFill");
return rc;
rc = PDMDevHlpIOPortRegister(pDevIns, VBE_PRINTF_PORT, 1, NULL, vgaIOPortWriteBIOS, vgaIOPortReadBIOS, NULL, NULL, "VGA BIOS debug/panic");
return rc;
rc = PDMDevHlpIOPortRegisterR0(pDevIns, VBE_PRINTF_PORT, 1, 0, "vgaIOPortWriteBIOS", "vgaIOPortReadBIOS", NULL, NULL, "VGA BIOS debug/panic");
return rc;
Log(("vgaConstruct: Failed to open VGA BIOS ROM file '%s', rc=%Rrc!\n", pThis->pszVgaBiosFile, rc));
AssertReleaseMsg(g_cbVgaBiosBinary <= _64K && g_cbVgaBiosBinary >= 32*_1K, ("g_cbVgaBiosBinary=%#x\n", g_cbVgaBiosBinary));
AssertReleaseMsg(RT_ALIGN_Z(g_cbVgaBiosBinary, PAGE_SIZE) == g_cbVgaBiosBinary, ("g_cbVgaBiosBinary=%#x\n", g_cbVgaBiosBinary));
return rc;
return rc;
return rc;
/*AssertMsg(pThis->Dev.devfn == 16 || iInstance != 0, ("pThis->Dev.devfn=%d\n", pThis->Dev.devfn));*/
Log(("!!WARNING!!: pThis->dev.devfn=%d (ignore if testcase or not started by Main)\n", pThis->Dev.devfn));
rc = PDMDevHlpPCIIORegionRegister(pDevIns, 0 /* iRegion */, pThis->vram_size, PCI_ADDRESS_SPACE_MEM_PREFETCH, vgaR3IORegionMap);
return rc;
return rc;
return rc;
return rc;
#ifdef VBE_NEW_DYN_LIST
cyReduction = 0;
cCustomModes = 0;
return VERR_NO_MEMORY;
# ifndef VRAM_SIZE_FIX
for (i = 0; i < MODE_INFO_SIZE; i++)
* pixelWidth;
pCurMode++;
if (cyReduction)
# ifndef VRAM_SIZE_FIX
pCurMode++;
if (cCustomModes)
AssertMsgFailed(("Configuration error: Invalid mode data '%s' for '%s'! cBits=%d\n", pszExtraData, szExtraDataKey, cBits));
return VERR_VGA_INVALID_CUSTOM_MODE;
# ifdef VRAM_SIZE_FIX
AssertMsgFailed(("Configuration error: custom video mode %dx%dx%dbits is too large for the virtual video memory of %dMb. Please increase the video memory size.\n",
return VERR_VGA_INVALID_CUSTOM_MODE;
switch (cBits)
pDefMode++;
pCurMode++;
return rc;
rc = PDMDevHlpIOPortRegister(pDevIns, VBE_EXTRA_PORT, 1, NULL, vbeIOPortWriteVBEExtra, vbeIOPortReadVBEExtra, NULL, NULL, "VBE BIOS Extra Data");
return rc;
rc = PDMDevHlpIOPortRegister(pDevIns, LOGO_IO_PORT, 1, NULL, vbeIOPortWriteCMDLogo, vbeIOPortReadCMDLogo, NULL, NULL, "BIOS Logo");
return rc;
PDMDevHlpDBGFInfoRegister(pDevIns, "vgatext", "Display VGA memory formatted as text.", vgaInfoText);
pThis->pu8Logo = (uint8_t *)PDMDevHlpMMHeapAlloc(pDevIns, RT_MAX(pThis->cbLogo, g_cbVgaDefBiosLogo + sizeof(LogoHdr)));
#ifdef VBOX_WITH_HGSMI
#ifdef VBOX_WITH_VDMA
STAM_REG(pVM, &pThis->StatRZMemoryRead, STAMTYPE_PROFILE, "/Devices/VGA/RZ/MMIO-Read", STAMUNIT_TICKS_PER_CALL, "Profiling of the VGAGCMemoryRead() body.");
STAM_REG(pVM, &pThis->StatR3MemoryRead, STAMTYPE_PROFILE, "/Devices/VGA/R3/MMIO-Read", STAMUNIT_TICKS_PER_CALL, "Profiling of the VGAGCMemoryRead() body.");
STAM_REG(pVM, &pThis->StatRZMemoryWrite, STAMTYPE_PROFILE, "/Devices/VGA/RZ/MMIO-Write", STAMUNIT_TICKS_PER_CALL, "Profiling of the VGAGCMemoryWrite() body.");
STAM_REG(pVM, &pThis->StatR3MemoryWrite, STAMTYPE_PROFILE, "/Devices/VGA/R3/MMIO-Write", STAMUNIT_TICKS_PER_CALL, "Profiling of the VGAGCMemoryWrite() body.");
STAM_REG(pVM, &pThis->StatMapPage, STAMTYPE_COUNTER, "/Devices/VGA/MapPageCalls", STAMUNIT_OCCURENCES, "Calls to IOMMMIOMapMMIO2Page.");
STAM_REG(pVM, &pThis->StatUpdateDisp, STAMTYPE_COUNTER, "/Devices/VGA/UpdateDisplay", STAMUNIT_OCCURENCES, "Calls to vgaPortUpdateDisplay().");
return rc;
sizeof(VGASTATE),
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,