From a0e7ccf6864c196906d58b54cd0996b4dbc1b022 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Fri, 26 Oct 2007 10:41:07 +0100 Subject: [PATCH] x86, hvm: Allow Cirrus VGA BIOS to clear framebuffer with minimal PIO writes. Signed-off-by: Ben Guthro Signed-off-by: Gary Grebus --- tools/firmware/vgabios/clext.c | 26 +++++++++++++++++++------- tools/ioemu/hw/cirrus_vga.c | 12 ++++++++++++ 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/tools/firmware/vgabios/clext.c b/tools/firmware/vgabios/clext.c index 1eb3c69734..97ae080b2c 100644 --- a/tools/firmware/vgabios/clext.c +++ b/tools/firmware/vgabios/clext.c @@ -1489,14 +1489,26 @@ cirrus_clear_vram_1: mov dx, #0x3ce out dx, ax push ax - mov cx, #0xa000 - mov es, cx - xor di, di + +;; Windows Vista appears to be emulating this sequence as part of changing +;; screen resolution, but it generates 4096 writes per iteration. +;; Instead, use a magic register sequence to write the whole bank. +;;mov cx, #0xa000 +;;mov es, cx +;;xor di, di +;;mov ax, si +;;mov cx, #8192 +;;cld +;;rep +;; stosw mov ax, si - mov cx, #8192 - cld - rep - stosw + shl ax, #8 + mov al, #0xfe + out dx, ax ;; Low byte of value to be written to the bank + mov ax, si + mov al, #0xff + out dx, ax ;; High byte and trigger the write + pop ax inc ah cmp ah, bl diff --git a/tools/ioemu/hw/cirrus_vga.c b/tools/ioemu/hw/cirrus_vga.c index 2fd1626362..8a637c57fd 100644 --- a/tools/ioemu/hw/cirrus_vga.c +++ b/tools/ioemu/hw/cirrus_vga.c @@ -294,6 +294,7 @@ void *shared_vram; static void cirrus_bitblt_reset(CirrusVGAState *s); static void cirrus_update_memory_access(CirrusVGAState *s); +static void cirrus_vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val); /*************************************** * @@ -1497,6 +1498,17 @@ cirrus_hook_write_gr(CirrusVGAState * s, unsigned reg_index, int reg_value) case 0x31: // BLT STATUS/START cirrus_write_bitblt(s, reg_value); break; + + // Extension to allow BIOS to clear 16K VRAM bank in one operation + case 0xFE: + s->gr[reg_index] = reg_value; // Lower byte of value to be written + break; + case 0xFF: { + target_phys_addr_t addr; + for (addr = 0xa0000; addr < 0xa4000; addr += 2) + cirrus_vga_mem_writew(s, addr, (reg_value << 8) | s->gr[0xFE]); + } + break; default: #ifdef DEBUG_CIRRUS printf("cirrus: outport gr_index %02x, gr_value %02x\n", reg_index, -- 2.30.2