DevVGA.cpp revision bee7d755e710f26e4ccad601faef94ab9b60b731
fd9abdda70912b99b24e3bf1a38f26fde908a74cnd * VBox VGA/VESA device
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess * Copyright (C) 2006 InnoTek Systemberatung GmbH
96ad5d81ee4a2cc66a4ae19893efc8aa6d06fae7jailletc * This file is part of VirtualBox Open Source Edition (OSE), as
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess * available from http://www.virtualbox.org. This file is free software;
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess * you can redistribute it and/or modify it under the terms of the GNU
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen * General Public License as published by the Free Software Foundation,
2e545ce2450a9953665f701bb05350f0d3f26275nd * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen * distribution. VirtualBox OSE is distributed in the hope that it will
d29d9ab4614ff992b0e8de6e2b88d52b6f1f153erbowen * be useful, but WITHOUT ANY WARRANTY of any kind.
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess * If you received this file as part of a commercial VirtualBox
af33a4994ae2ff15bc67d19ff1a7feb906745bf8rbowen * distribution, then only the terms of your commercial VirtualBox
3f08db06526d6901aa08c110b5bc7dde6bc39905nd * license agreement apply instead of the previous paragraph.
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess * --------------------------------------------------------------------
3f08db06526d6901aa08c110b5bc7dde6bc39905nd * This code is based on:
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess * QEMU VGA Emulator.
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess * Copyright (c) 2003 Fabrice Bellard
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess * Permission is hereby granted, free of charge, to any person obtaining a copy
fac8c35bfb158112226ab43ddf84d59daca5dc30nd * of this software and associated documentation files (the "Software"), to deal
d474d8ef01ec5c2a09341cd148851ed383c3287crbowen * in the Software without restriction, including without limitation the rights
d474d8ef01ec5c2a09341cd148851ed383c3287crbowen * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess * copies of the Software, and to permit persons to whom the Software is
4b575a6b6704b516f22d65a3ad35696d7b9ba372rpluem * furnished to do so, subject to the following conditions:
4b575a6b6704b516f22d65a3ad35696d7b9ba372rpluem * The above copyright notice and this permission notice shall be included in
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess * all copies or substantial portions of the Software.
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30471a4650391f57975f60bbb6e4a90be7b284bfhumbedooh * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess * THE SOFTWARE.
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess/*******************************************************************************
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess* Defined Constants And Macros *
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess*******************************************************************************/
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess/** The default amount of VRAM. */
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess/** The maximum amount of VRAM. */
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess/** The minimum amount of VRAM. */
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess/** The maximum number of monitors. */
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess/** The size of the VGA GC mapping.
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess * This is supposed to be all the VGA memory accessible to the guest.
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess * The initial value was 256KB but NTAllInOne.iso appears to access more
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess * thus the limit was upped to 512KB.
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess * @todo Someone with some VGA knowhow should make a better guess at this value.
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess/** Converts a vga adaptor state pointer to a device instance pointer. */
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess#define VGASTATE2DEVINS(pVgaState) ((pVgaState)->CTXSUFF(pDevIns))
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess/** Use VBE bytewise I/O */
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess/** Use VBE new dynamic mode list.
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess * If this is not defined, no checks are carried out to see if the modes all
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess * fit into the framebuffer! See the VRAM_SIZE_FIX define. */
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess/** Check that the video modes fit into virtual video memory.
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess * Only works when VBE_NEW_DYN_LIST is defined! */
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess/** Some fixes to ensure that logical scan-line lengths are not overwritten. */
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess/*******************************************************************************
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess* Header Files *
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess*******************************************************************************/
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess#if defined(VBE_NEW_DYN_LIST) && defined(IN_RING3) && !defined(VBOX_DEVICE_STRUCT_TESTCASE)
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess/*******************************************************************************
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess* Internal Functions *
e655a84bbb62bb1c66993fda5e74b04feda14dc6kess*******************************************************************************/
e655a84bbb62bb1c66993fda5e74b04feda14dc6kessPDMBOTHCBDECL(int) vgaIOPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
e655a84bbb62bb1c66993fda5e74b04feda14dc6kessPDMBOTHCBDECL(int) vgaIOPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
e655a84bbb62bb1c66993fda5e74b04feda14dc6kessPDMBOTHCBDECL(int) vgaIOPortWriteVBEIndex(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
e655a84bbb62bb1c66993fda5e74b04feda14dc6kessPDMBOTHCBDECL(int) vgaIOPortWriteVBEData(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
e655a84bbb62bb1c66993fda5e74b04feda14dc6kessPDMBOTHCBDECL(int) vgaIOPortReadVBEIndex(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
e655a84bbb62bb1c66993fda5e74b04feda14dc6kessPDMBOTHCBDECL(int) vgaIOPortReadVBEData(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
e655a84bbb62bb1c66993fda5e74b04feda14dc6kessPDMBOTHCBDECL(int) vgaMMIOFill(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, uint32_t u32Item, unsigned cbItem, unsigned cItems);
e655a84bbb62bb1c66993fda5e74b04feda14dc6kessPDMBOTHCBDECL(int) vgaMMIORead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb);
1c8f2418892d98febb00a06b9a4f45f8bcfd80a3ndPDMBOTHCBDECL(int) vgaMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb);
fac8c35bfb158112226ab43ddf84d59daca5dc30ndPDMBOTHCBDECL(int) vgaGCLFBAccessHandler(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, RTGCPHYS GCPhysFault, void *pvUser);
727872d18412fc021f03969b8641810d8896820bhumbedoohPDMBOTHCBDECL(int) vgaR0LFBAccessHandler(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, RTGCPHYS GCPhysFault, void *pvUser);
0d0ba3a410038e179b695446bb149cce6264e0abndPDMBOTHCBDECL(int) vbeIOPortReadVBEExtra(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
cc7e1025de9ac63bd4db6fe7f71c158b2cf09fe4humbedoohPDMBOTHCBDECL(int) vbeIOPortWriteVBEExtra(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
0d0ba3a410038e179b695446bb149cce6264e0abnd#endif /* IN_RING3 */
727872d18412fc021f03969b8641810d8896820bhumbedooh * Set a VRAM page dirty.
0d0ba3a410038e179b695446bb149cce6264e0abnd * @param pData VGA instance data.
30471a4650391f57975f60bbb6e4a90be7b284bfhumbedooh * @param offVRAM The VRAM offset of the page to set.
af33a4994ae2ff15bc67d19ff1a7feb906745bf8rbowenDECLINLINE(void) vga_set_dirty(VGAState *pData, RTGCPHYS offVRAM)
7fec19672a491661b2fe4b29f685bc7f4efa64d4nd AssertMsg(offVRAM < pData->vram_size, ("offVRAM = %p, pData->vram_size = %p\n", offVRAM, pData->vram_size));
7fec19672a491661b2fe4b29f685bc7f4efa64d4nd ASMBitSet(&pData->au32DirtyBitmap[0], offVRAM >> PAGE_SHIFT);
AssertMsg(offVRAM < pData->vram_size, ("offVRAM = %p, pData->vram_size = %p\n", offVRAM, pData->vram_size));
#ifndef VBOX_DEVICE_STRUCT_TESTCASE
#ifndef VBOX
#include "vl.h"
#include "vga_int.h"
#ifdef LOG_ENABLED
#define DEBUG_BOCHS_VBE
#ifdef VBOX
#ifdef VBOX
((uint32_t)( \
#ifdef WORDS_BIGENDIAN
#define PAT(x) (x)
#ifdef WORDS_BIGENDIAN
#define BIG 0
#ifdef WORDS_BIGENDIAN
#ifdef WORDS_BIGENDIAN
#define PAT(x) (x)
#ifndef VBOX
int vga_io_memory;
/* check port range access depending on color/monochrome mode */
switch(addr) {
if (s->ar_flip_flop == 0) {
val = 0;
val = 0;
#ifdef DEBUG_VGA_REG
s->dac_sub_index = 0;
s->dac_read_index++;
#ifdef DEBUG_VGA_REG
#ifdef DEBUG_VGA_REG
s->ar_flip_flop = 0;
#if defined(DEBUG_VGA)
return val;
int index;
/* check port range access depending on color/monochrome mode */
#ifdef DEBUG_VGA
switch(addr) {
if (s->ar_flip_flop == 0) {
switch(index) {
#ifndef VBOX
#ifdef DEBUG_VGA_REG
s->dac_sub_index = 0;
s->dac_sub_index = 0;
s->dac_state = 0;
s->dac_sub_index = 0;
s->dac_write_index++;
#ifdef DEBUG_VGA_REG
#ifdef DEBUG_VGA_REG
switch(s->cr_index) {
#ifdef CONFIG_BOCHS_VBE
return val;
switch(s->vbe_index) {
case VBE_DISPI_INDEX_XRES:
case VBE_DISPI_INDEX_YRES:
case VBE_DISPI_INDEX_BPP:
val = 0;
#ifdef DEBUG_BOCHS_VBE
return val;
#ifdef DEBUG_BOCHS_VBE
switch(s->vbe_index) {
case VBE_DISPI_INDEX_ID:
case VBE_DISPI_INDEX_XRES:
#ifdef KEEP_SCAN_LINE_LENGTH
s->vbe_start_addr = 0;
case VBE_DISPI_INDEX_YRES:
#ifdef KEEP_SCAN_LINE_LENGTH
s->vbe_start_addr = 0;
case VBE_DISPI_INDEX_BPP:
if (val == 0)
#ifdef KEEP_SCAN_LINE_LENGTH
s->vbe_start_addr = 0;
case VBE_DISPI_INDEX_BANK:
case VBE_DISPI_INDEX_ENABLE:
int h, shift_control;
#ifdef VBOX
#ifndef KEEP_SCAN_LINE_LENGTH
#ifndef KEEP_SCAN_LINE_LENGTH
s->vbe_start_addr = 0;
#ifndef VBOX
shift_control = 0;
#ifdef VBOX
s->bank_offset = 0;
#ifdef VBOX
#ifdef IN_RING3
int w, h, line_offset;
w = val;
case VBE_DISPI_INDEX_X_OFFSET:
case VBE_DISPI_INDEX_Y_OFFSET:
#ifdef VBOX
switch(memory_map_mode) {
#ifdef IN_GC
return VINF_IOM_HC_MMIO_WRITE;
#ifndef VBOX
#ifndef VBOX
#ifndef VBOX
return ret;
#ifndef VBOX
uint32_t v;
#ifdef TARGET_WORDS_BIGENDIAN
uint32_t v;
#ifdef TARGET_WORDS_BIGENDIAN
#ifdef VBOX
#ifdef DEBUG_VGA_MEM
switch(memory_map_mode) {
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
#ifndef VBOX
#ifdef IN_GC
return VINF_IOM_HC_MMIO_WRITE;
return VINF_SUCCESS;
#ifdef DEBUG_VGA_MEM
#ifndef VBOX
#ifndef VBOX
#ifdef IN_GC
return VINF_IOM_HC_MMIO_WRITE;
return VINF_SUCCESS;
#ifdef DEBUG_VGA_MEM
#ifndef VBOX
#ifdef IN_GC
return VINF_IOM_HC_MMIO_WRITE;
return VINF_SUCCESS;
switch(write_mode) {
goto do_write;
switch(func_select) {
#ifndef VBOX
#ifdef DEBUG_VGA_MEM
#ifndef VBOX
return VINF_SUCCESS;
#ifndef VBOX
#ifdef TARGET_WORDS_BIGENDIAN
#ifdef TARGET_WORDS_BIGENDIAN
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;
int full_update, i;
full_update = 0;
v = s->ar[i];
return full_update;
int full_update, i;
full_update = 0;
return full_update;
#ifdef CONFIG_BOCHS_VBE
int full_update;
full_update = 0;
return full_update;
switch(depth) {
#ifndef VBOX
#ifndef VBOX
#ifndef VBOX
s->plane_updated = 0;
#ifndef VBOX
#ifndef VBOX
#ifndef VBOX
return VINF_SUCCESS;
#ifndef VBOX
return rc;
#ifndef VBOX
#ifndef VBOX
#ifdef WORDS_BIGENDIAN
dup9 = 0;
ch_attr_ptr++;
#ifndef VBOX
#ifdef VBOX
return VINF_SUCCESS;
int ret;
#ifdef CONFIG_BOCHS_VBE
ret = 0;
return ret;
#ifdef CONFIG_BOCHS_VBE
#ifndef VBOX
#ifdef VBOX
return rc;
if (s->shift_control == 0)
update_palette16(s);
update_palette16(s);
return VINF_SUCCESS;
#ifndef VBOX
uint8_t *d;
bool 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;
#ifndef VBOX
|| offsets_changed)
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);
#ifndef VBOX
#ifndef VBOX
y1 = 0;
for(y = 0; y < height; y++) {
int shift;
#ifndef VBOX
if (update) {
if (y_start < 0)
y_start = y;
#ifndef VBOX
if (s->fRenderVRAM)
if (s->cursor_draw_line)
s->cursor_draw_line(s, d, y);
if (y_start >= 0) {
#ifndef VBOX
if (!multi_run) {
y1++;
multi_run--;
addr1 = 0;
d += linesize;
if (y_start >= 0) {
#ifndef VBOX
#ifndef VBOX
#ifdef VBOX
return VINF_SUCCESS;
#ifndef VBOX
int i, w, val;
uint8_t *d;
if (!full_update)
val = 0;
for(i = 0; i < s->last_scr_height; i++) {
int i, w, val;
uint8_t *d;
if (!full_update)
val = 0;
for(i = 0; i < (int)s->last_scr_height; i++) {
d += cbScanline;
#define GMODE_TEXT 0
#ifndef VBOX
void vga_update_display(void)
#ifndef VBOX
#ifndef VBOX
full_update = 0;
switch(graphic_mode) {
case GMODE_TEXT:
#ifdef VBOX
rc =
case GMODE_GRAPH:
#ifdef VBOX
rc =
case GMODE_BLANK:
#ifdef VBOX
return rc;
#ifndef VBOX
void vga_invalidate_display(void)
#ifndef VBOX
#ifdef CONFIG_BOCHS_VBE
for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
qemu_put_byte(f, 0);
int is_vbe, i;
#ifndef VBOX
return -EINVAL;
#ifdef CONFIG_BOCHS_VBE
if (!is_vbe)
#ifndef VBOX
return -EINVAL;
for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
if (is_vbe)
#ifndef VBOX
return -EINVAL;
static void vga_init_expand(void)
expand4[i] = v;
expand2[i] = v;
expand4to8[i] = v;
#ifdef VBOX
vga_reset(s);
vga_state = s;
VGAState *s;
s->bank_offset = 0;
#ifdef CONFIG_BOCHS_VBE
#if defined (TARGET_I386)
if (bus) {
PCIDevice *d;
sizeof(PCIDevice),
#ifdef CONFIG_BOCHS_VBE
#ifndef VBOX
#ifndef VBOX
if (!s->data)
vga_save_w = w;
vga_save_h = h;
int w, int h, int linesize)
FILE *f;
d = d1;
v = *(uint32_t *)d;
fclose(f);
//@@TODO (dmik): implement stretching/shrinking!
int bpp;
for (y = 0; y < height; y ++)
PDMBOTHCBDECL(int) vgaIOPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
return VINF_SUCCESS;
PDMBOTHCBDECL(int) vgaIOPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
return VINF_SUCCESS;
return VINF_SUCCESS;
return VERR_IOM_IOPORT_UNUSED;
PDMBOTHCBDECL(int) vgaIOPortWriteVBEData(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
#ifdef IN_GC
return VINF_IOM_HC_IOPORT_WRITE;
#ifdef VBE_BYTEWISE_IO
if (!s->fWriteVBEData)
s->fWriteVBEData = false;
return VINF_SUCCESS;
s->fWriteVBEData = true;
return VINF_SUCCESS;
s->fWriteVBEData = false;
// Log(("vgaIOPortWriteVBEData: VBE_DISPI_INDEX_ENABLE & VBE_DISPI_ENABLED - Switching to host...\n"));
return VINF_SUCCESS;
PDMBOTHCBDECL(int) vgaIOPortWriteVBEIndex(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
#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)
#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)
#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;
* 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)
uint32_t b;
for (i = 0; i < cbItem; i++)
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
#ifdef IN_GC
return VINF_IOM_HC_MMIO_WRITE;
return VINF_SUCCESS;
while (cItems-- > 0)
for (i = 0; i < cbItem; i++)
GCPhysAddr++;
#ifdef IN_GC
return VINF_IOM_HC_MMIO_WRITE;
return VINF_SUCCESS;
while (cItems-- > 0)
for (i = 0; i < cbItem; i++)
GCPhysAddr++;
#ifdef IN_GC
return VINF_IOM_HC_MMIO_WRITE;
return VINF_SUCCESS;
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 *)pData->CTXSUFF(vram_ptr))[GCPhysAddr] = (((uint32_t *)pData->CTXSUFF(vram_ptr))[GCPhysAddr] & ~write_mask) | (aVal[0] & write_mask);
GCPhysAddr++;
while (cItems-- > 0)
((uint32_t *)pData->CTXSUFF(vram_ptr))[GCPhysAddr] = (((uint32_t *)pData->CTXSUFF(vram_ptr))[GCPhysAddr] & ~write_mask) | (aVal[0] & write_mask);
GCPhysAddr++;
((uint32_t *)pData->CTXSUFF(vram_ptr))[GCPhysAddr] = (((uint32_t *)pData->CTXSUFF(vram_ptr))[GCPhysAddr] & ~write_mask) | (aVal[1] & write_mask);
GCPhysAddr++;
while (cItems-- > 0)
for (i = 0; i < cbItem; i++)
((uint32_t *)pData->CTXSUFF(vram_ptr))[GCPhysAddr] = (((uint32_t *)pData->CTXSUFF(vram_ptr))[GCPhysAddr] & ~write_mask) | (aVal[i] & write_mask);
GCPhysAddr++;
return VINF_SUCCESS;
PDMBOTHCBDECL(int) vgaMMIORead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
switch (cb)
while (cb-- > 0)
return VINF_SUCCESS;
PDMBOTHCBDECL(int) vgaMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
switch (cb)
return rc;
int rc;
#ifndef IN_RING3
return VINF_SUCCESS;
return VINF_SUCCESS;
return rc;
#ifdef IN_GC
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;
#ifdef IN_RING3
# ifdef VBE_NEW_DYN_LIST
PDMBOTHCBDECL(int) vbeIOPortWriteVBEExtra(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
return VINF_SUCCESS;
return VINF_SUCCESS;
PDMBOTHCBDECL(int) vbeIOPortReadVBEExtra(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
return VINF_SUCCESS;
*pu32 = 0;
Log(("vbeIOPortReadVBEExtra: Requested address is out of VBE data!!! Address=%#x(%d) cbVBEExtraData=%#x(%d)\n",
pData->u16VBEExtraAddress, pData->u16VBEExtraAddress, pData->cbVBEExtraData, pData->cbVBEExtraData));
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
return VERR_IOM_IOPORT_UNUSED;
static DECLCALLBACK(int) vgaIOPortReadBIOS(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
return VERR_IOM_IOPORT_UNUSED;
static DECLCALLBACK(int) vgaIOPortWriteBIOS(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
switch (u32)
if (lastWasNotNewline == 0)
lastWasNotNewline = 0;
return VINF_SUCCESS;
return VINF_SUCCESS;
switch (enmInterface)
case PDMINTERFACE_BASE:
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, Port)) )
#ifdef DEBUG_sunlover
return rc;
return VINF_SUCCESS;
#ifdef DEBUG_sunlover
static DECLCALLBACK(int) vgaPortSetRefreshRate(PPDMIDISPLAYPORT pInterface, uint32_t cMilliesInterval)
if (cMilliesInterval)
if (!pcBits)
return VERR_INVALID_PARAMETER;
return VINF_SUCCESS;
static DECLCALLBACK(int) vgaPortSnapshot(PPDMIDISPLAYPORT pInterface, void *pvData, size_t cbData, uint32_t *pcx, uint32_t *pcy, size_t *pcbData)
/* @todo r=sunlover: replace the method with a direct VRAM rendering like in vgaPortUpdateDisplayRect. */
LogFlow(("vgaPortSnapshot: pvData=%p cbData=%d pcx=%p pcy=%p pcbData=%p\n", pvData, cbData, pcx, pcy, pcbData));
if (!pvData)
return VERR_INVALID_PARAMETER;
Log(("vgaPortSnapshot: %d bytes are required, a buffer of %d bytes is profiled.\n", cbRequired, cbData));
return VERR_BUFFER_OVERFLOW;
return rc;
if (pcx)
if (pcy)
if (pcbData)
LogFlow(("vgaPortSnapshot: returns VINF_SUCCESS (cx=%d cy=%d cbData=%d)\n", Connector.cx, Connector.cy, cbRequired));
return VINF_SUCCESS;
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(pData->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
#ifndef VBOX
#ifndef VBOX
#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
static DECLCALLBACK(int) vgaR3IORegionMap(PPCIDEVICE pPciDev, /*unsigned*/ int iRegion, RTGCPHYS GCPhysAddress, uint32_t cb, PCIADDRESSSPACE enmType)
int rc;
LogFlow(("vgaR3IORegionMap: iRegion=%d GCPhysAddress=%VGp cb=%#x enmType=%d\n", iRegion, GCPhysAddress, cb, enmType));
rc = MMR3PhysRegister(pVM, pData->vram_ptrHC, GCPhysAddress, pData->vram_size, MM_RAM_FLAGS_MMIO2, "VRam");
return VINF_SUCCESS;
return rc;
return VERR_INTERNAL_ERROR;
return VINF_SUCCESS;
static DECLCALLBACK(int) vgaR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle, uint32_t u32Version)
return VINF_SUCCESS;
char *pchStart;
char *pchEnd;
switch(graphic_mode)
case GMODE_TEXT:
int x_incr;
int line_offset;
# ifdef WORDS_BIGENDIAN
#ifdef CONFIG_BOCHS_VBE
if (offDelta)
switch (iLUN)
pData->pDrv = (PDMIDISPLAYCONNECTOR*)pData->pDrvBase->pfnQueryInterface(pData->pDrvBase, PDMINTERFACE_DISPLAY_CONNECTOR);
Log(("%s/%d: warning: no driver attached to LUN #0!\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
return rc;
return VERR_PDM_NO_SUCH_LUN;
switch (iLUN)
static bool fExpandDone = false;
int rc;
#ifdef VBE_NEW_DYN_LIST
unsigned cb;
if (!fExpandDone)
fExpandDone = true;
rc = PDMR3GetSymbolGCLazy(pVM, pDevIns->pDevReg->szGCMod, "vgaGCLFBAccessHandler", &pData->GCPtrLFBHandler);
AssertReleaseMsgFailed(("PDMR3GetSymbolGC(, %s, \"vgaGCLFBAccessHandler\",) -> %Vrc\n", pDevIns->pDevReg->szGCMod, rc));
return rc;
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 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 = PDMDevHlpIOPortRegister(pDevIns, 0xff80, 1, NULL, vgaIOPortWriteVBEIndex, vgaIOPortReadVBEIndex, "VGA/VBE - Index Old");
return rc;
rc = PDMDevHlpIOPortRegister(pDevIns, 0xff81, 1, NULL, vgaIOPortWriteVBEData, vgaIOPortReadVBEData, "VGA/VBE - Data Old");
return rc;
rc = PDMDevHlpIOPortRegisterGC(pDevIns, 0x3c0, 16, 0, "vgaIOPortWrite", "vgaIOPortRead", NULL, NULL, "VGA - 3c0 (GC)");
return rc;
rc = PDMDevHlpIOPortRegisterGC(pDevIns, 0x3b4, 2, 0, "vgaIOPortWrite", "vgaIOPortRead", NULL, NULL, "VGA - 3b4 (GC)");
return rc;
rc = PDMDevHlpIOPortRegisterGC(pDevIns, 0x3ba, 1, 0, "vgaIOPortWrite", "vgaIOPortRead", NULL, NULL, "VGA - 3ba (GC)");
return rc;
rc = PDMDevHlpIOPortRegisterGC(pDevIns, 0x3d4, 2, 0, "vgaIOPortWrite", "vgaIOPortRead", NULL, NULL, "VGA - 3d4 (GC)");
return rc;
rc = PDMDevHlpIOPortRegisterGC(pDevIns, 0x3da, 1, 0, "vgaIOPortWrite", "vgaIOPortRead", NULL, NULL, "VGA - 3da (GC)");
return rc;
#ifdef CONFIG_BOCHS_VBE
rc = PDMDevHlpIOPortRegisterGC(pDevIns, 0x1ce, 1, 0, "vgaIOPortWriteVBEIndex", "vgaIOPortReadVBEIndex", NULL, NULL, "VGA/VBE - Index (GC)");
return rc;
rc = PDMDevHlpIOPortRegisterGC(pDevIns, 0x1cf, 1, 0, "vgaIOPortWriteVBEData", "vgaIOPortReadVBEData", NULL, NULL, "VGA/VBE - Data (GC)");
return rc;
rc = PDMDevHlpIOPortRegisterGC(pDevIns, 0xff80, 1, 0, "vgaIOPortWriteVBEIndex", "vgaIOPortReadVBEIndex", "VGA/VBE - Index Old (GC)");
return rc;
rc = PDMDevHlpIOPortRegisterGC(pDevIns, 0xff81, 1, 0, "vgaIOPortWriteVBEData", "vgaIOPortReadVBEData", "VGA/VBE - Index Old (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 = PDMDevHlpIOPortRegisterR0(pDevIns, 0xff80, 1, 0, "vgaIOPortWriteVBEIndex", "vgaIOPortReadVBEIndex", "VGA/VBE - Index Old (GC)");
return rc;
rc = PDMDevHlpIOPortRegisterR0(pDevIns, 0xff81, 1, 0, "vgaIOPortWriteVBEData", "vgaIOPortReadVBEData", "VGA/VBE - Index Old (GC)");
return rc;
rc = PDMDevHlpMMIORegister(pDevIns, 0x000a0000, 0x00020000, 0, vgaMMIOWrite, vgaMMIORead, vgaMMIOFill, "VGA - VGA Video Buffer");
return rc;
rc = PDMDevHlpMMIORegisterGC(pDevIns, 0x000a0000, 0x00020000, 0, "vgaMMIOWrite", "vgaMMIORead", "vgaMMIOFill", "VGA - VGA Video Buffer");
return rc;
rc = PDMDevHlpMMIORegisterR0(pDevIns, 0x000a0000, 0x00020000, 0, "vgaMMIOWrite", "vgaMMIORead", "vgaMMIOFill", "VGA - VGA Video Buffer");
return rc;
rc = PDMDevHlpIOPortRegister(pDevIns, VBE_PRINTF_PORT, 1, NULL, vgaIOPortWriteBIOS, vgaIOPortReadBIOS, NULL, NULL, "VGA BIOS debug/panic");
return 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));
rc = PDMDevHlpROMRegister(pDevIns, 0x000c0000, g_cbVgaBiosBinary, &g_abVgaBiosBinary[0], "VGA BIOS");
return rc;
rc = PDMDevHlpSSMRegister(pDevIns, pDevIns->pDevReg->szDeviceName, iInstance, 1 /* version */, sizeof(*pData),
return rc;
return rc;
/*AssertMsg(pData->Dev.devfn == 16 || iInstance != 0, ("pData->Dev.devfn=%d\n", pData->Dev.devfn));*/
Log(("!!WARNING!!: pData->dev.devfn=%d (ignore if testcase or no started by Main)\n", pData->Dev.devfn));
rc = PDMDevHlpPCIIORegionRegister(pDevIns, 0, pData->vram_size, PCI_ADDRESS_SPACE_MEM_PREFETCH, vgaR3IORegionMap);
return rc;
rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_REAL, vgaTimerRefresh, "VGA Refresh Timer", &pData->RefreshTimer);
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++;
switch (cBits)
pCurMode++;
return rc;
rc = PDMDevHlpIOPortRegister(pDevIns, VBE_EXTRA_PORT, 1, NULL, vbeIOPortWriteVBEExtra, vbeIOPortReadVBEExtra, NULL, NULL, "VBE BIOS Extra Data");
return rc;
STAM_REG(pVM, &pData->StatGCMemoryRead, STAMTYPE_PROFILE, "/Devices/VGA/GC/Memory/Read", STAMUNIT_TICKS_PER_CALL, "Profiling of the VGAGCMemoryRead() body.");
STAM_REG(pVM, &pData->StatGCMemoryWrite, STAMTYPE_PROFILE, "/Devices/VGA/GC/Memory/Write", STAMUNIT_TICKS_PER_CALL, "Profiling of the VGAGCMemoryWrite() body.");
STAM_REG(pVM, &pData->StatGCIOPortRead, STAMTYPE_PROFILE, "/Devices/VGA/GC/IOPort/Read", STAMUNIT_TICKS_PER_CALL, "Profiling of the VGAGCIOPortRead() body.");
STAM_REG(pVM, &pData->StatGCIOPortWrite, STAMTYPE_PROFILE, "/Devices/VGA/GC/IOPort/Write", STAMUNIT_TICKS_PER_CALL, "Profiling of the VGAGCIOPortWrite() body.");
return VINF_SUCCESS;
#ifdef VBE_NEW_DYN_LIST
return rc;
return VINF_SUCCESS;
PDM_DEVREG_FLAGS_HOST_BITS_DEFAULT | PDM_DEVREG_FLAGS_GUEST_BITS_DEFAULT | PDM_DEVREG_FLAGS_GC | PDM_DEVREG_FLAGS_R0,
sizeof(VGASTATE),
NULL,
NULL,
NULL,
NULL,
NULL,