DevVGA.cpp revision 3956d0151065a11e49d2213b38a5efdad46807e0
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * DevVGA - VBox VGA/VESA device.
b2bc8de1367ae24e1b27b53921d0b32ee3df7acdvboxsync * Copyright (C) 2006-2007 Oracle Corporation
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * available from http://www.virtualbox.org. This file is free software;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * you can redistribute it and/or modify it under the terms of the GNU
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * General Public License (GPL) as published by the Free Software
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * --------------------------------------------------------------------
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * This code is based on:
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * QEMU VGA Emulator.
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync * Copyright (c) 2003 Fabrice Bellard
b2bc8de1367ae24e1b27b53921d0b32ee3df7acdvboxsync * Permission is hereby granted, free of charge, to any person obtaining a copy
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * of this software and associated documentation files (the "Software"), to deal
2f0d866e126dd288169fed591c259c1c6b4016e5vboxsync * in the Software without restriction, including without limitation the rights
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * copies of the Software, and to permit persons to whom the Software is
f5e53763b0a581b0299e98028c6c52192eb06785vboxsync * furnished to do so, subject to the following conditions:
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * The above copyright notice and this permission notice shall be included in
2f0d866e126dd288169fed591c259c1c6b4016e5vboxsync * all copies or substantial portions of the Software.
2f0d866e126dd288169fed591c259c1c6b4016e5vboxsync * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
9b7ab382b3f9667e8847020e1e58f7143c4d2334vboxsync * THE SOFTWARE.
8742e4a4ddb7b62d21d96d56dd1baf01c9f22cecvboxsync/*******************************************************************************
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync* Defined Constants And Macros *
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync*******************************************************************************/
8742e4a4ddb7b62d21d96d56dd1baf01c9f22cecvboxsync/* WARNING!!! All defines that affetc VGAState should be placed to DevVGA.h !!!
8742e4a4ddb7b62d21d96d56dd1baf01c9f22cecvboxsync * NEVER place them here as this would lead to VGAState inconsistency
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync * across different .cpp files !!!
63787aca0a2a16ec959a5294148726ccf898ddf1vboxsync/** The size of the VGA GC mapping.
63787aca0a2a16ec959a5294148726ccf898ddf1vboxsync * This is supposed to be all the VGA memory accessible to the guest.
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * The initial value was 256KB but NTAllInOne.iso appears to access more
63787aca0a2a16ec959a5294148726ccf898ddf1vboxsync * thus the limit was upped to 512KB.
63787aca0a2a16ec959a5294148726ccf898ddf1vboxsync * @todo Someone with some VGA knowhow should make a better guess at this value.
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync#define PCIDEV_2_VGASTATE(pPciDev) ((VGAState *)((uintptr_t)pPciDev - RT_OFFSETOF(VGAState, Dev)))
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync#endif /* VBOX_WITH_HGSMI */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync/** Converts a vga adaptor state pointer to a device instance pointer. */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync#define VGASTATE2DEVINS(pVgaState) ((pVgaState)->CTX_SUFF(pDevIns))
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync/** Check that the video modes fit into virtual video memory.
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * Only works when VBE_NEW_DYN_LIST is defined! */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync/** Check buffer if an VRAM offset is within the right range or not. */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync#if defined(IN_RC) || defined(VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0)
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync AssertMsgReturn((off) < (pThis)->vram_size, ("%RX32 !< %RX32\n", (uint32_t)(off), (pThis)->vram_size), VINF_SUCCESS); \
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync Log2(("%Rfn[%d]: %RX32 -> R3\n", __PRETTY_FUNCTION__, __LINE__, (off))); \
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync } while (0)
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync AssertMsgReturn((off) < (pThis)->vram_size, ("%RX32 !< %RX32\n", (uint32_t)(off), (pThis)->vram_size), VINF_SUCCESS)
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync/** Check buffer if an VRAM offset is within the right range or not. */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync#if defined(IN_RC) || defined(VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0)
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync# define VERIFY_VRAM_READ_OFF_RETURN(pThis, off, rcVar) \
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync AssertMsgReturn((off) < (pThis)->vram_size, ("%RX32 !< %RX32\n", (uint32_t)(off), (pThis)->vram_size), 0xff); \
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync Log2(("%Rfn[%d]: %RX32 -> R3\n", __PRETTY_FUNCTION__, __LINE__, (off))); \
7c48fdac0546978ed14617c8096734ce2d18c8e5vboxsync return 0; \
7c48fdac0546978ed14617c8096734ce2d18c8e5vboxsync } while (0)
7c48fdac0546978ed14617c8096734ce2d18c8e5vboxsync# define VERIFY_VRAM_READ_OFF_RETURN(pThis, off, rcVar) \
7c48fdac0546978ed14617c8096734ce2d18c8e5vboxsync AssertMsgReturn((off) < (pThis)->vram_size, ("%RX32 !< %RX32\n", (uint32_t)(off), (pThis)->vram_size), 0xff)
9b7ab382b3f9667e8847020e1e58f7143c4d2334vboxsync/*******************************************************************************
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync* Header Files *
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync*******************************************************************************/
b2bc8de1367ae24e1b27b53921d0b32ee3df7acdvboxsync#endif /* IN_RING3 */
c060166f65b9dd2f1ed53e6e4cffdad948e01722vboxsync/* should go BEFORE any other DevVGA include to make all DevVGA.h config defines be visible */
c060166f65b9dd2f1ed53e6e4cffdad948e01722vboxsync#if defined(VBE_NEW_DYN_LIST) && defined(IN_RING3) && !defined(VBOX_DEVICE_STRUCT_TESTCASE)
e562a8bb17c0dfa1c316708e085a3a92fcc80521vboxsync/*******************************************************************************
e562a8bb17c0dfa1c316708e085a3a92fcc80521vboxsync* Structures and Typedefs *
e562a8bb17c0dfa1c316708e085a3a92fcc80521vboxsync*******************************************************************************/
e562a8bb17c0dfa1c316708e085a3a92fcc80521vboxsync/** BMP File Format Bitmap Header. */
e562a8bb17c0dfa1c316708e085a3a92fcc80521vboxsynctypedef struct
e562a8bb17c0dfa1c316708e085a3a92fcc80521vboxsync/** Pointer to a bitmap header*/
e562a8bb17c0dfa1c316708e085a3a92fcc80521vboxsync/** OS/2 1.x Information Header Format. */
e562a8bb17c0dfa1c316708e085a3a92fcc80521vboxsynctypedef struct
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync/** Pointer to a OS/2 1.x header format */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync/** OS/2 2.0 Information Header Format. */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsynctypedef struct
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync uint32_t Compression; /* Compression Scheme (0=none) */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync uint32_t XPelsPerMeter; /* Horz. Resolution in Pixels/Meter */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync uint32_t YPelsPerMeter; /* Vert. Resolution in Pixels/Meter */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync uint32_t ClrUsed; /* Number of Colors in Color Table */
b2bc8de1367ae24e1b27b53921d0b32ee3df7acdvboxsync uint32_t ClrImportant; /* Number of Important Colors */
b2bc8de1367ae24e1b27b53921d0b32ee3df7acdvboxsync uint16_t Reserved; /* Reserved FIelds (always 0) */
b2bc8de1367ae24e1b27b53921d0b32ee3df7acdvboxsync uint16_t Rendering; /* Halftone Algorithm Used on Image */
b2bc8de1367ae24e1b27b53921d0b32ee3df7acdvboxsync uint32_t ColorEncoding; /* Color Table Format (always 0) */
b2bc8de1367ae24e1b27b53921d0b32ee3df7acdvboxsync uint32_t Identifier; /* Misc. Field for Application Use */
b2bc8de1367ae24e1b27b53921d0b32ee3df7acdvboxsync/** Pointer to a OS/2 2.0 header format */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync/** Windows 3.x Information Header Format. */
b2bc8de1367ae24e1b27b53921d0b32ee3df7acdvboxsynctypedef struct
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync uint32_t Compression; /* Compression Scheme (0=none) */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync uint32_t XPelsPerMeter; /* Horz. Resolution in Pixels/Meter */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync uint32_t YPelsPerMeter; /* Vert. Resolution in Pixels/Meter */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync uint32_t ClrUsed; /* Number of Colors in Color Table */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync uint32_t ClrImportant; /* Number of Important Colors */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync/** Pointer to a Windows 3.x header format */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync/** @name BMP compressions.
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync/** @name BMP header sizes.
63787aca0a2a16ec959a5294148726ccf898ddf1vboxsync/** The BIOS boot menu text position, X. */
63787aca0a2a16ec959a5294148726ccf898ddf1vboxsync/** The BIOS boot menu text position, Y. */
8287c906b9b1d215824d4cdf6c1eaf40681ebfa8vboxsync/** Width of the "Press F12 to select boot device." bitmap.
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync Anything that exceeds the limit of F12BootText below is filled with
8287c906b9b1d215824d4cdf6c1eaf40681ebfa8vboxsync background. */
8287c906b9b1d215824d4cdf6c1eaf40681ebfa8vboxsync/** Height of the boot device selection bitmap, see LOGO_F12TEXT_WIDTH. */
9540eeb13face31ddc1c5f15338556fe46f18a77vboxsync/** The BIOS logo delay time (msec). */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync#define LOGO_MAX_SIZE LOGO_MAX_WIDTH * LOGO_MAX_HEIGHT * 4
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync/*******************************************************************************
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync* Global Variables *
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync*******************************************************************************/
b2bc8de1367ae24e1b27b53921d0b32ee3df7acdvboxsync/* "Press F12 to select boot device." bitmap. */
7c48fdac0546978ed14617c8096734ce2d18c8e5vboxsync 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
7c48fdac0546978ed14617c8096734ce2d18c8e5vboxsync 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
7c48fdac0546978ed14617c8096734ce2d18c8e5vboxsync 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0x0F, 0x7C,
7c48fdac0546978ed14617c8096734ce2d18c8e5vboxsync 0xF8, 0xF0, 0x01, 0xE0, 0x81, 0x9F, 0x3F, 0x00, 0x70, 0xF8, 0x00, 0xE0, 0xC3,
b2bc8de1367ae24e1b27b53921d0b32ee3df7acdvboxsync 0x07, 0x0F, 0x1F, 0x3E, 0x70, 0x00, 0xF0, 0xE1, 0xC3, 0x07, 0x0E, 0x00, 0x6E,
7c48fdac0546978ed14617c8096734ce2d18c8e5vboxsync 0x7C, 0x60, 0xE0, 0xE1, 0xC3, 0x07, 0xC6, 0x80, 0x81, 0x31, 0x63, 0xC6, 0x00,
b2bc8de1367ae24e1b27b53921d0b32ee3df7acdvboxsync 0x30, 0x80, 0x61, 0x0C, 0x00, 0x36, 0x63, 0x00, 0x8C, 0x19, 0x83, 0x61, 0xCC,
7c48fdac0546978ed14617c8096734ce2d18c8e5vboxsync 0x18, 0x36, 0x00, 0xCC, 0x8C, 0x19, 0xC3, 0x06, 0xC0, 0x8C, 0x31, 0x3C, 0x30,
7c48fdac0546978ed14617c8096734ce2d18c8e5vboxsync 0x8C, 0x19, 0x83, 0x31, 0x60, 0x60, 0x00, 0x0C, 0x18, 0x00, 0x0C, 0x60, 0x18,
7c48fdac0546978ed14617c8096734ce2d18c8e5vboxsync 0x00, 0x80, 0xC1, 0x18, 0x00, 0x30, 0x06, 0x60, 0x18, 0x30, 0x80, 0x01, 0x00,
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync 0x33, 0x63, 0xC6, 0x30, 0x00, 0x30, 0x63, 0x80, 0x19, 0x0C, 0x03, 0x06, 0x00,
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync 0x0C, 0x18, 0x18, 0xC0, 0x81, 0x03, 0x00, 0x03, 0x18, 0x0C, 0x00, 0x60, 0x30,
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync 0x06, 0x00, 0x87, 0x01, 0x18, 0x06, 0x0C, 0x60, 0x00, 0xC0, 0xCC, 0x98, 0x31,
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync 0x0C, 0x00, 0xCC, 0x18, 0x30, 0x0C, 0xC3, 0x80, 0x01, 0x00, 0x03, 0x66, 0xFE,
7c48fdac0546978ed14617c8096734ce2d18c8e5vboxsync 0x18, 0x30, 0x00, 0xC0, 0x02, 0x06, 0x06, 0x00, 0x18, 0x8C, 0x01, 0x60, 0xE0,
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync 0x0F, 0x86, 0x3F, 0x03, 0x18, 0x00, 0x30, 0x33, 0x66, 0x0C, 0x03, 0x00, 0x33,
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync 0xFE, 0x0C, 0xC3, 0x30, 0xE0, 0x0F, 0xC0, 0x87, 0x9B, 0x31, 0x63, 0xC6, 0x00,
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync 0xF0, 0x80, 0x01, 0x03, 0x00, 0x06, 0x63, 0x00, 0x8C, 0x19, 0x83, 0x61, 0xCC,
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync 0x18, 0x06, 0x00, 0x6C, 0x8C, 0x19, 0xC3, 0x00, 0x80, 0x8D, 0x31, 0xC3, 0x30,
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync 0x8C, 0x19, 0x03, 0x30, 0xB3, 0xC3, 0x87, 0x0F, 0x1F, 0x00, 0x2C, 0x60, 0x80,
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync 0x01, 0xE0, 0x87, 0x0F, 0x00, 0x3E, 0x7C, 0x60, 0xF0, 0xE1, 0xE3, 0x07, 0x00,
63787aca0a2a16ec959a5294148726ccf898ddf1vboxsync 0x0F, 0x3E, 0x7C, 0xFC, 0x00, 0xC0, 0xC3, 0xC7, 0x30, 0x0E, 0x3E, 0x7C, 0x00,
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync 0xCC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x1E, 0xC0, 0x00, 0x60, 0x00,
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x60, 0x00, 0xC0, 0x00, 0x00, 0x00,
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync 0x0C, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00,
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync 0x00, 0x00, 0x00, 0xC0, 0x0C, 0x87, 0x31, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00,
63787aca0a2a16ec959a5294148726ccf898ddf1vboxsync 0x00, 0x06, 0x00, 0x00, 0x18, 0x00, 0x30, 0x00, 0x00, 0x00, 0x03, 0x00, 0x30,
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xE0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync 0xF8, 0x83, 0xC1, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00,
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync 0x00, 0x04, 0x00, 0x0E, 0x00, 0x00, 0x80, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x30,
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
b2bc8de1367ae24e1b27b53921d0b32ee3df7acdvboxsync/*******************************************************************************
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync* Internal Functions *
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync*******************************************************************************/
7c48fdac0546978ed14617c8096734ce2d18c8e5vboxsyncPDMBOTHCBDECL(int) vgaIOPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsyncPDMBOTHCBDECL(int) vgaIOPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsyncPDMBOTHCBDECL(int) vgaIOPortWriteVBEIndex(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
762a68c2bb3ccde807330e3d1cb05f8b244a5f72vboxsyncPDMBOTHCBDECL(int) vgaIOPortWriteVBEData(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsyncPDMBOTHCBDECL(int) vgaIOPortReadVBEIndex(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsyncPDMBOTHCBDECL(int) vgaIOPortReadVBEData(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsyncPDMBOTHCBDECL(int) vgaMMIOFill(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, uint32_t u32Item, unsigned cbItem, unsigned cItems);
7c48fdac0546978ed14617c8096734ce2d18c8e5vboxsyncPDMBOTHCBDECL(int) vgaMMIORead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb);
7c48fdac0546978ed14617c8096734ce2d18c8e5vboxsyncPDMBOTHCBDECL(int) vgaMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb);
7c48fdac0546978ed14617c8096734ce2d18c8e5vboxsyncPDMBOTHCBDECL(int) vgaIOPortReadBIOS(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsyncPDMBOTHCBDECL(int) vgaIOPortWriteBIOS(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsyncPDMBOTHCBDECL(int) vgaGCLFBAccessHandler(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, RTGCPHYS GCPhysFault, void *pvUser);
7c48fdac0546978ed14617c8096734ce2d18c8e5vboxsyncPDMBOTHCBDECL(int) vgaR0LFBAccessHandler(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, RTGCPHYS GCPhysFault, void *pvUser);
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsyncPDMBOTHCBDECL(int) vbeIOPortReadVBEExtra(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsyncPDMBOTHCBDECL(int) vbeIOPortWriteVBEExtra(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsyncPDMBOTHCBDECL(int) vbeIOPortReadCMDLogo(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
b2bc8de1367ae24e1b27b53921d0b32ee3df7acdvboxsyncPDMBOTHCBDECL(int) vbeIOPortWriteCMDLogo(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync#endif /* IN_RING3 */
b2bc8de1367ae24e1b27b53921d0b32ee3df7acdvboxsync * Set a VRAM page dirty.
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * @param pThis VGA instance data.
7697e43970d863558b6c168a55e8948ccb18d8d1vboxsync * @param offVRAM The VRAM offset of the page to set.
7697e43970d863558b6c168a55e8948ccb18d8d1vboxsyncDECLINLINE(void) vga_set_dirty(VGAState *pThis, RTGCPHYS offVRAM)
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync AssertMsg(offVRAM < pThis->vram_size, ("offVRAM = %p, pThis->vram_size = %p\n", offVRAM, pThis->vram_size));
b2bc8de1367ae24e1b27b53921d0b32ee3df7acdvboxsync ASMBitSet(&pThis->au32DirtyBitmap[0], offVRAM >> PAGE_SHIFT);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * Tests if a VRAM page is dirty.
b2bc8de1367ae24e1b27b53921d0b32ee3df7acdvboxsync * @returns true if dirty.
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * @returns false if clean.
b2bc8de1367ae24e1b27b53921d0b32ee3df7acdvboxsync * @param pThis VGA instance data.
b2bc8de1367ae24e1b27b53921d0b32ee3df7acdvboxsync * @param offVRAM The VRAM offset of the page to check.
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsyncDECLINLINE(bool) vga_is_dirty(VGAState *pThis, RTGCPHYS offVRAM)
b2bc8de1367ae24e1b27b53921d0b32ee3df7acdvboxsync AssertMsg(offVRAM < pThis->vram_size, ("offVRAM = %p, pThis->vram_size = %p\n", offVRAM, pThis->vram_size));
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync return ASMBitTest(&pThis->au32DirtyBitmap[0], offVRAM >> PAGE_SHIFT);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * Reset dirty flags in a give range.
b2bc8de1367ae24e1b27b53921d0b32ee3df7acdvboxsync * @param pThis VGA instance data.
b2bc8de1367ae24e1b27b53921d0b32ee3df7acdvboxsync * @param offVRAMStart Offset into the VRAM buffer of the first page.
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * @param offVRAMEnd Offset into the VRAM buffer of the last page - exclusive.
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsyncDECLINLINE(void) vga_reset_dirty(VGAState *pThis, RTGCPHYS offVRAMStart, RTGCPHYS offVRAMEnd)
9674ed871d32468dd791ad601151f46d2e843350vboxsync ASMBitClearRange(&pThis->au32DirtyBitmap[0], offVRAMStart >> PAGE_SHIFT, offVRAMEnd >> PAGE_SHIFT);
9674ed871d32468dd791ad601151f46d2e843350vboxsync/* force some bits to zero */
3956d0151065a11e49d2213b38a5efdad46807e0vboxsync (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
b2bc8de1367ae24e1b27b53921d0b32ee3df7acdvboxsync (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \
7c48fdac0546978ed14617c8096734ce2d18c8e5vboxsync (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \
b2bc8de1367ae24e1b27b53921d0b32ee3df7acdvboxsync (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
e562a8bb17c0dfa1c316708e085a3a92fcc80521vboxsync#define PAT(x) (x)
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync#define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff)
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync#define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff)
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync#define PAT(x) (x)
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync#endif /* IN_RING3 */
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync/* Update the values needed for calculating Vertical Retrace and
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * Display Enable status bits more or less accurately. The Display Enable
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * bit is set (indicating *disabled* display signal) when either the
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync * horizontal (hblank) or vertical (vblank) blanking is active. The
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync * Vertical Retrace bit is set when vertical retrace (vsync) is active.
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * Unless the CRTC is horribly misprogrammed, vsync implies vblank.
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync unsigned htotal_cclks, vtotal_lines, chars_per_sec;
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync unsigned hblank_start_cclk, hblank_end_cclk, hblank_width, hblank_skew_cclks;
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync unsigned vblank_start_line, vblank_end, vblank_width;
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync const int clocks[] = {25175000, 28322000, 25175000, 25175000};
e562a8bb17c0dfa1c316708e085a3a92fcc80521vboxsync /* For horizontal timings, we only care about the blanking start/end. */
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync hblank_end_cclk = (s->cr[0x03] & 0x1f) + ((s->cr[0x05] & 0x80) >> 2);
e562a8bb17c0dfa1c316708e085a3a92fcc80521vboxsync /* For vertical timings, we need both the blanking start/end... */
e562a8bb17c0dfa1c316708e085a3a92fcc80521vboxsync vtotal_lines = s->cr[0x06] + ((s->cr[0x07] & 1) << 8) + ((s->cr[0x07] & 0x20) << 4) + 2;
63787aca0a2a16ec959a5294148726ccf898ddf1vboxsync vblank_start_line = s->cr[0x15] + ((s->cr[0x07] & 8) << 5) + ((s->cr[0x09] & 0x20) << 4);
f2a212e40c7307d2b8ef9b2658a539f5ac41e683vboxsync /* ... and the vertical retrace (vsync) start/end. */
f2a212e40c7307d2b8ef9b2658a539f5ac41e683vboxsync vsync_start_line = s->cr[0x10] + ((s->cr[0x07] & 4) << 6) + ((s->cr[0x07] & 0x80) << 2);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync /* Calculate the blanking and sync widths. The way it's implemented in
b2bc8de1367ae24e1b27b53921d0b32ee3df7acdvboxsync * the VGA with limited-width compare counters is quite a piece of work.
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync hblank_width = (hblank_end_cclk - hblank_start_cclk) & 0x3f;/* 6 bits */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync vblank_width = (vblank_end - vblank_start_line) & 0xff; /* 8 bits */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync vsync_width = (vsync_end - vsync_start_line) & 0xf; /* 4 bits */
e562a8bb17c0dfa1c316708e085a3a92fcc80521vboxsync /* Calculate the dot and character clock rates. */
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync clock_doubled = (s->sr[0x01] >> 3) & 1; /* Clock doubling bit. */
7c48fdac0546978ed14617c8096734ce2d18c8e5vboxsync char_dots = (s->sr[0x01] & 1) ? 8 : 9; /* 8 or 9 dots per cclk. */
7c48fdac0546978ed14617c8096734ce2d18c8e5vboxsync Assert(chars_per_sec); /* Can't possibly be zero. */
7c48fdac0546978ed14617c8096734ce2d18c8e5vboxsync /* Calculate the number of cclks per entire frame. */
7c48fdac0546978ed14617c8096734ce2d18c8e5vboxsync Assert(r->frame_cclks); /* Can't possibly be zero. */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync if (r->v_freq_hz) { /* Could be set to emulate a specific rate. */
7c48fdac0546978ed14617c8096734ce2d18c8e5vboxsync r->cclk_ns = 1000000000 / (r->frame_cclks * r->v_freq_hz);
f2a212e40c7307d2b8ef9b2658a539f5ac41e683vboxsync /* Calculate timings in cclks/lines. Stored but not directly used. */
f2a212e40c7307d2b8ef9b2658a539f5ac41e683vboxsync r->hb_start = hblank_start_cclk + hblank_skew_cclks;
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync r->hb_end = hblank_start_cclk + hblank_width + hblank_skew_cclks;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync /* Calculate timings in nanoseconds. For easier comparisons, the frame
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * is considered to start at the beginning of the vertical and horizontal
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * blanking period.
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync r->vs_start_ns = (r->vs_start - r->vb_start) * r->h_total_ns;
e562a8bb17c0dfa1c316708e085a3a92fcc80521vboxsync r->vs_end_ns = (r->vs_end - r->vb_start) * r->h_total_ns;
b2bc8de1367ae24e1b27b53921d0b32ee3df7acdvboxsync uint8_t val = s->st01 & ~(ST01_V_RETRACE | ST01_DISP_ENABLE);
b2bc8de1367ae24e1b27b53921d0b32ee3df7acdvboxsync time_ns = PDMDevHlpTMTimeVirtGetNano(VGASTATE2DEVINS(s));
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync /* Determine the time within the frame. */
36fbf6dcd3e6b2e5891456b730577ff0eb355c9fvboxsync /* See if we're in the vertical blanking period... */
e562a8bb17c0dfa1c316708e085a3a92fcc80521vboxsync /* ... and additionally in the vertical sync period. */
e562a8bb17c0dfa1c316708e085a3a92fcc80521vboxsync if (cur_frame_ns >= r->vs_start_ns && cur_frame_ns <= r->vs_end_ns)
e562a8bb17c0dfa1c316708e085a3a92fcc80521vboxsync /* Determine the time within the current scanline. */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync /* See if we're in the horizontal blanking period. */
e562a8bb17c0dfa1c316708e085a3a92fcc80521vboxsync return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync /* Color */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync /* Monochrome */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsyncstatic uint32_t vga_ioport_read(void *opaque, uint32_t addr)
e562a8bb17c0dfa1c316708e085a3a92fcc80521vboxsync /* check port range access depending on color/monochrome mode */
b2bc8de1367ae24e1b27b53921d0b32ee3df7acdvboxsync case 0x3c0:
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync if (s->ar_flip_flop == 0) {
8a54ed337392872c7cfcfb96f173468bbbb0f7fcvboxsync case 0x3c1:
8a54ed337392872c7cfcfb96f173468bbbb0f7fcvboxsync case 0x3c2:
8a54ed337392872c7cfcfb96f173468bbbb0f7fcvboxsync case 0x3c4:
e562a8bb17c0dfa1c316708e085a3a92fcc80521vboxsync case 0x3c5:
8a54ed337392872c7cfcfb96f173468bbbb0f7fcvboxsync Log2(("vga: read SR%x = 0x%02x\n", s->sr_index, val));
8a54ed337392872c7cfcfb96f173468bbbb0f7fcvboxsync case 0x3c7:
63787aca0a2a16ec959a5294148726ccf898ddf1vboxsync case 0x3c8:
8a54ed337392872c7cfcfb96f173468bbbb0f7fcvboxsync case 0x3c9:
8a54ed337392872c7cfcfb96f173468bbbb0f7fcvboxsync val = s->palette[s->dac_read_index * 3 + s->dac_sub_index];
8a54ed337392872c7cfcfb96f173468bbbb0f7fcvboxsync case 0x3ca:
e562a8bb17c0dfa1c316708e085a3a92fcc80521vboxsync case 0x3cc:
8a54ed337392872c7cfcfb96f173468bbbb0f7fcvboxsync case 0x3ce:
8a54ed337392872c7cfcfb96f173468bbbb0f7fcvboxsync case 0x3cf:
8a54ed337392872c7cfcfb96f173468bbbb0f7fcvboxsync Log2(("vga: read GR%x = 0x%02x\n", s->gr_index, val));
8a54ed337392872c7cfcfb96f173468bbbb0f7fcvboxsync case 0x3b4:
8a54ed337392872c7cfcfb96f173468bbbb0f7fcvboxsync case 0x3d4:
8a54ed337392872c7cfcfb96f173468bbbb0f7fcvboxsync case 0x3b5:
8a54ed337392872c7cfcfb96f173468bbbb0f7fcvboxsync case 0x3d5:
e562a8bb17c0dfa1c316708e085a3a92fcc80521vboxsync Log2(("vga: read CR%x = 0x%02x\n", s->cr_index, val));
8a54ed337392872c7cfcfb96f173468bbbb0f7fcvboxsync case 0x3ba:
8a54ed337392872c7cfcfb96f173468bbbb0f7fcvboxsync case 0x3da:
8a54ed337392872c7cfcfb96f173468bbbb0f7fcvboxsync Log(("VGA: read addr=0x%04x data=0x%02x\n", addr, val));
8a54ed337392872c7cfcfb96f173468bbbb0f7fcvboxsyncstatic void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
8a54ed337392872c7cfcfb96f173468bbbb0f7fcvboxsync Log(("VGA: write addr=0x%04x data=0x%02x\n", addr, val));
8a54ed337392872c7cfcfb96f173468bbbb0f7fcvboxsync /* check port range access depending on color/monochrome mode */
8a54ed337392872c7cfcfb96f173468bbbb0f7fcvboxsync case 0x3c0:
8a54ed337392872c7cfcfb96f173468bbbb0f7fcvboxsync if (s->ar_flip_flop == 0) {
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
e562a8bb17c0dfa1c316708e085a3a92fcc80521vboxsync case 0x3c2:
3614117c1132a61599e6190939e775cafe549411vboxsync case 0x3c4:
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync case 0x3c5:
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync Log2(("vga: write SR%x = 0x%02x\n", s->sr_index, val));
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync /* The VGA region is (could be) affected by this change; reset all aliases we've created. */
e562a8bb17c0dfa1c316708e085a3a92fcc80521vboxsync IOMMMIOResetRegion(PDMDevHlpGetVM(s->CTX_SUFF(pDevIns)), 0x000a0000);
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync case 0x3c7:
b2bc8de1367ae24e1b27b53921d0b32ee3df7acdvboxsync case 0x3c8:
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync case 0x3c9:
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3);
e562a8bb17c0dfa1c316708e085a3a92fcc80521vboxsync case 0x3ce:
b2bc8de1367ae24e1b27b53921d0b32ee3df7acdvboxsync case 0x3cf:
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync Log2(("vga: write GR%x = 0x%02x\n", s->gr_index, val));
762a68c2bb3ccde807330e3d1cb05f8b244a5f72vboxsync /* The VGA region is (could be) affected by this change; reset all aliases we've created. */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync IOMMMIOResetRegion(PDMDevHlpGetVM(s->CTX_SUFF(pDevIns)), 0x000a0000);
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync case 0x3b4:
e562a8bb17c0dfa1c316708e085a3a92fcc80521vboxsync case 0x3d4:
b2bc8de1367ae24e1b27b53921d0b32ee3df7acdvboxsync case 0x3b5:
ac6445a70a26cb69d08734f1d9dbc171cec86cd8vboxsync case 0x3d5:
ac6445a70a26cb69d08734f1d9dbc171cec86cd8vboxsync Log2(("vga: write CR%x = 0x%02x\n", s->cr_index, val));
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync /* handle CR0-7 protection */
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync /* can always write bit 4 of CR7 */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync /* The following registers are only updated during a mode set. */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync switch(s->cr_index) {
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync case 0x3ba:
e562a8bb17c0dfa1c316708e085a3a92fcc80521vboxsync case 0x3da:
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsyncstatic uint32_t vbe_ioport_read_index(void *opaque, uint32_t addr)
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsyncstatic uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr)
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_GETCAPS) {
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync /* XXX: do not hardcode ? */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync /* Reading from the port means that the old additions are requesting the number of monitors. */
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync Log(("VBE: read index=0x%x val=0x%x\n", s->vbe_index, val));
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync#define VBE_PITCH_ALIGN 4 /* Align pitch to 32 bits - Qt requires that. */
e562a8bb17c0dfa1c316708e085a3a92fcc80521vboxsync/* Calculate scanline pitch based on bit depth and width in pixels. */
e562a8bb17c0dfa1c316708e085a3a92fcc80521vboxsyncstatic uint32_t calc_line_pitch(uint16_t bpp, uint16_t width)
e562a8bb17c0dfa1c316708e085a3a92fcc80521vboxsync /* Align the pitch to some sensible value. */
e562a8bb17c0dfa1c316708e085a3a92fcc80521vboxsync aligned_pitch = (pitch + (VBE_PITCH_ALIGN - 1)) & ~(VBE_PITCH_ALIGN - 1);
e562a8bb17c0dfa1c316708e085a3a92fcc80521vboxsync Log(("VBE: Line pitch %d aligned to %d bytes\n", pitch, aligned_pitch));
e562a8bb17c0dfa1c316708e085a3a92fcc80521vboxsync/* Calculate line width in pixels based on bit depth and pitch. */
e562a8bb17c0dfa1c316708e085a3a92fcc80521vboxsyncstatic uint32_t calc_line_width(uint16_t bpp, uint32_t pitch)
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsyncstatic void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val)
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsyncstatic int vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync bool fRecalculate = false;
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync Log(("VBE: write index=0x%x val=0x%x\n", s->vbe_index, val));
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync#endif /* VBOX_WITH_HGSMI */
b2bc8de1367ae24e1b27b53921d0b32ee3df7acdvboxsync max_bank = s->vbe_bank_max >> 2; /* Each bank really covers 256K */
ac6445a70a26cb69d08734f1d9dbc171cec86cd8vboxsync /* Old software may pass garbage in the high byte of bank. If the maximum
ac6445a70a26cb69d08734f1d9dbc171cec86cd8vboxsync * bank fits into a single byte, toss the high byte the user supplied.
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync /* The VGA region is (could be) affected by this change; reset all aliases we've created. */
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync IOMMMIOResetRegion(PDMDevHlpGetVM(s->CTX_SUFF(pDevIns)), 0x000a0000);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync !(s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED)) {
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync /* Check the values before we screw up with a resolution which is too big or small. */
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync cb = s->vbe_regs[VBE_DISPI_INDEX_XRES] * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync uint16_t cVirtWidth = s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH];
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync AssertMsgFailed(("VIRT WIDTH=%d YRES=%d cb=%d vram_size=%d\n",
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH], s->vbe_regs[VBE_DISPI_INDEX_YRES], cb, s->vram_size));
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync return VINF_SUCCESS; /* Note: silent failure like before */
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync /* When VBE interface is enabled, it is reset. */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync /* clear the screen (should be done in BIOS) */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync uint16_t cY = RT_MIN(s->vbe_regs[VBE_DISPI_INDEX_YRES],
23603ed361f22874964e3a841add2c58ec2bb1eavboxsync /* we initialize the VGA graphic mode (should be done
23603ed361f22874964e3a841add2c58ec2bb1eavboxsync in BIOS) */
b2bc8de1367ae24e1b27b53921d0b32ee3df7acdvboxsync s->gr[0x06] = (s->gr[0x06] & ~0x0c) | 0x05; /* graphic mode + memory map 1 */
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync /* width */
9b7ab382b3f9667e8847020e1e58f7143c4d2334vboxsync /* height (only meaningful if < 1024) */
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync /* line compare to 1023 */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync s->gr[0x05] = (s->gr[0x05] & ~0x60) | (shift_control << 5);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync /* sunlover 30.05.2007
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * The ar_index remains with bit 0x20 cleared after a switch from fullscreen
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync * DOS mode on Windows XP guest. That leads to GMODE_BLANK in vga_update_display.
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * But the VBE mode is graphics, so not a blank anymore.
b2bc8de1367ae24e1b27b53921d0b32ee3df7acdvboxsync /* XXX: the bios should do that */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync /* sunlover 21.12.2006
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * Here is probably more to reset. When this was executed in GC
b2bc8de1367ae24e1b27b53921d0b32ee3df7acdvboxsync * then the *update* functions could not detect a mode change.
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * Or may be these update function should take the s->vbe_regs[s->vbe_index]
b2bc8de1367ae24e1b27b53921d0b32ee3df7acdvboxsync * into account when detecting a mode change.
b2bc8de1367ae24e1b27b53921d0b32ee3df7acdvboxsync * The 'mode reset not detected' problem is now fixed by executing the
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * VBE_DISPI_INDEX_ENABLE case always in RING3 in order to call the
b2bc8de1367ae24e1b27b53921d0b32ee3df7acdvboxsync * LFBChange callback.
b2bc8de1367ae24e1b27b53921d0b32ee3df7acdvboxsync * LFB video mode is either disabled or changed. This notification
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * is used by the display to disable VBVA.
b2bc8de1367ae24e1b27b53921d0b32ee3df7acdvboxsync s->pDrv->pfnLFBModeChange(s->pDrv, (val & VBE_DISPI_ENABLED) != 0);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync /* The VGA region is (could be) affected by this change; reset all aliases we've created. */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync IOMMMIOResetRegion(PDMDevHlpGetVM(s->CTX_SUFF(pDevIns)), 0x000a0000);
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync#endif /* IN_RING3 */
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync /* Changes in the VGA device are minimal. The device is bypassed. The driver does all work. */
63787aca0a2a16ec959a5294148726ccf898ddf1vboxsync else if (val == VBOX_VIDEO_INTERPRET_ADAPTER_MEMORY)
63787aca0a2a16ec959a5294148726ccf898ddf1vboxsync s->pDrv->pfnProcessAdapterData(s->pDrv, s->CTX_SUFF(vram_ptr), s->vram_size);
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync else if ((val & 0xFFFF0000) == VBOX_VIDEO_INTERPRET_DISPLAY_MEMORY_BASE)
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync s->pDrv->pfnProcessDisplayData(s->pDrv, s->CTX_SUFF(vram_ptr), val & 0xFFFF);
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync#endif /* IN_RING3 */
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync uint16_t cVirtWidth = s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH];
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync uint16_t offX = s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET];
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync uint16_t offY = s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET];
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync return VINF_SUCCESS; /* Not enough data has been set yet. */
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync uint32_t cbLinePitch = calc_line_pitch(cBPP, cVirtWidth);
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync s->vbe_line_offset = RT_MIN(cbLinePitch, s->vram_size);
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync s->vbe_start_addr = RT_MIN(offStart, s->vram_size);
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = cVirtHeight;
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync/* called for accesses between 0xa0000 and 0xc0000 */
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsyncstatic uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr, int *prc)
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync /* convert to VGA memory offset */
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync RTGCPHYS GCPhys = addr; /* save original address */
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync return 0xff;
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync return 0xff;
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync return 0xff;
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync /* chain 4 mode : simplest access */
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync /* If all planes are accessible, then map the page to the frame buffer and make it writable. */
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync /** @todo only allow read access (doesn't work now) */
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync IOMMMIOMapMMIO2Page(PDMDevHlpGetVM(s->CTX_SUFF(pDevIns)), GCPhys, s->GCPhysVRAM + addr, X86_PTE_RW|X86_PTE_P);
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync /* Set as dirty as write accesses won't be noticed now. */
63e3a547845f7c31bb4e892a66684b560dc63611vboxsync# endif /* IN_RC */
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync } else if (!(s->sr[4] & 0x04)) { /* Host access is controlled by SR4, not GR5! */
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync /* odd/even mode (aka text mode mapping) */
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync /* See the comment for a similar line in vga_mem_writeb. */
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync /* standard VGA latched access */
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync s->latch = ((uint32_t *)s->CTX_SUFF(vram_ptr))[addr];
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync /* read mode 0 */
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync /* read mode 1 */
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync ret = (s->latch ^ mask16[s->gr[2]]) & mask16[s->gr[7]];
63787aca0a2a16ec959a5294148726ccf898ddf1vboxsync/* called for accesses between 0xa0000 and 0xc0000 */
63787aca0a2a16ec959a5294148726ccf898ddf1vboxsyncstatic int vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
d5a801e98910a0c3c9c65cfc7cf8826f0b0b4450vboxsync int memory_map_mode, plane, write_mode, b, func_select, mask;
63e3a547845f7c31bb4e892a66684b560dc63611vboxsync /* convert to VGA memory offset */
d5a801e98910a0c3c9c65cfc7cf8826f0b0b4450vboxsync RTGCPHYS GCPhys = addr; /* save original address */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync /* chain 4 mode : simplest access */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync /* If all planes are accessible, then map the page to the frame buffer and make it writable. */
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync IOMMMIOMapMMIO2Page(PDMDevHlpGetVM(s->CTX_SUFF(pDevIns)), GCPhys, s->GCPhysVRAM + addr, X86_PTE_RW | X86_PTE_P);
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync# endif /* IN_RC */
04cdb3815f28f5dbf0e7dffc7957fec59260e76fvboxsync s->plane_updated |= mask; /* only used to detect font change */
63e3a547845f7c31bb4e892a66684b560dc63611vboxsync } else if (!(s->sr[4] & 0x04)) { /* Host access is controlled by SR4, not GR5! */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync /* odd/even mode (aka text mode mapping) */
8287c906b9b1d215824d4cdf6c1eaf40681ebfa8vboxsync /* 'addr' is offset in a plane, bit 0 selects the plane.
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync * Mask the bit 0, convert plane index to vram offset,
7c48fdac0546978ed14617c8096734ce2d18c8e5vboxsync * that is multiply by the number of planes,
b2bc8de1367ae24e1b27b53921d0b32ee3df7acdvboxsync * and select the plane byte in the vram offset.
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync s->plane_updated |= mask; /* only used to detect font change */
b2bc8de1367ae24e1b27b53921d0b32ee3df7acdvboxsync /* standard VGA latched access */
04cdb3815f28f5dbf0e7dffc7957fec59260e76fvboxsync if (((++s->cLatchAccesses) & s->uMaskLatchAccess) == s->uMaskLatchAccess)
04cdb3815f28f5dbf0e7dffc7957fec59260e76fvboxsync static uint32_t const s_aMask[5] = { 0x3ff, 0x1ff, 0x7f, 0x3f, 0x1f};
04cdb3815f28f5dbf0e7dffc7957fec59260e76fvboxsync static uint64_t const s_aDelta[5] = {10000000, 5000000, 2500000, 1250000, 625000};
04cdb3815f28f5dbf0e7dffc7957fec59260e76fvboxsync if (PDMDevHlpCanEmulateIoBlock(s->CTX_SUFF(pDevIns)))
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync /* About 1000 (or more) accesses per 10 ms will trigger a reschedule
63787aca0a2a16ec959a5294148726ccf898ddf1vboxsync * to the recompiler
63787aca0a2a16ec959a5294148726ccf898ddf1vboxsync if (u64CurTime - s->u64LastLatchedAccess < s_aDelta[s->iMask])
8742e4a4ddb7b62d21d96d56dd1baf01c9f22cecvboxsync s->iMask = RT_MIN(s->iMask + 1U, RT_ELEMENTS(s_aMask) - 1U);
762a68c2bb3ccde807330e3d1cb05f8b244a5f72vboxsync Log2(("Reset mask (was %d) delta %RX64 (limit %x)\n", s->iMask, u64CurTime - s->u64LastLatchedAccess, s_aDelta[s->iMask]));
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync /* rotate */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync /* apply set/reset mask */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync val = (val & ~set_mask) | (mask16[s->gr[0]] & set_mask);
fe554d9c0e3a6de4ba221610ac95a44c7d288e01vboxsync /* rotate */
8287c906b9b1d215824d4cdf6c1eaf40681ebfa8vboxsync /* apply logical operation */
572f495840b063427930dbb6f5a81f3147286effvboxsync /* nothing to do */
8287c906b9b1d215824d4cdf6c1eaf40681ebfa8vboxsync /* apply bit mask */
3ebd5757516d21eccdad25ddd456d2913c2fb215vboxsync /* mask data according to sr[2] */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync s->plane_updated |= mask; /* only used to detect font change */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync (((uint32_t *)s->CTX_SUFF(vram_ptr))[addr] & ~write_mask) |
b2bc8de1367ae24e1b27b53921d0b32ee3df7acdvboxsync Log3(("vga: latch: [0x%x] mask=0x%08x val=0x%08x\n",
a96f8709d113c056da40edb8e2591983226a9761vboxsynctypedef void vga_draw_glyph8_func(uint8_t *d, int linesize,
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsynctypedef void vga_draw_glyph9_func(uint8_t *d, int linesize,
8287c906b9b1d215824d4cdf6c1eaf40681ebfa8vboxsynctypedef void vga_draw_line_func(VGAState *s1, uint8_t *d,
8287c906b9b1d215824d4cdf6c1eaf40681ebfa8vboxsyncstatic inline unsigned int rgb_to_pixel8(unsigned int r, unsigned int g, unsigned b)
b2bc8de1367ae24e1b27b53921d0b32ee3df7acdvboxsync return ((r >> 5) << 5) | ((g >> 5) << 2) | (b >> 6);
fb9af443dbf06990f4956d683286ddce29c4dca6vboxsyncstatic inline unsigned int rgb_to_pixel15(unsigned int r, unsigned int g, unsigned b)
8287c906b9b1d215824d4cdf6c1eaf40681ebfa8vboxsync return ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
8287c906b9b1d215824d4cdf6c1eaf40681ebfa8vboxsyncstatic inline unsigned int rgb_to_pixel16(unsigned int r, unsigned int g, unsigned b)
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync return ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
8287c906b9b1d215824d4cdf6c1eaf40681ebfa8vboxsyncstatic inline unsigned int rgb_to_pixel32(unsigned int r, unsigned int g, unsigned b)
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsyncstatic unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync unsigned int col;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsyncstatic unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b)
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync unsigned int col;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsyncstatic unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b)
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync unsigned int col;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsyncstatic unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync unsigned int col;
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync/* return true if the palette was modified */
016096e367cd20c3d3c3fd9a6650b55935c2e31dvboxsync for(i = 0; i < 16; i++) {
return full_update;
int full_update, i;
int wide_dac;
full_update = 0;
if (wide_dac)
return full_update;
#ifdef CONFIG_BOCHS_VBE
int full_update;
full_update = 0;
return full_update;
switch(depth) {
s->plane_updated = 0;
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;
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;
int offsets_changed;
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;
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
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;
full_update = 0;
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++)
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 *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 (pbSrc)
if (!cbLine)
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, cbRequired, Connector.cx, Connector.cy));
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,