diff --git a/cpu-all.h b/cpu-all.h index 2879c11e6a8228e230c08482e508f4c6991331f3..e1bdc9133db5f6273f3d415b4e4d80cc7b9d2408 100644 --- a/cpu-all.h +++ b/cpu-all.h @@ -692,6 +692,8 @@ int cpu_register_io_memory(int io_index, CPUReadMemoryFunc **mem_read, CPUWriteMemoryFunc **mem_write, void *opaque); +CPUWriteMemoryFunc **cpu_get_io_memory_write(int io_index); +CPUReadMemoryFunc **cpu_get_io_memory_read(int io_index); void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, int len, int is_write); diff --git a/exec.c b/exec.c index 95883beca325e7b9165ff590c875312aff15bf9e..5f2a87c239f0c222ae965c1e8dadacf7f9307e03 100644 --- a/exec.c +++ b/exec.c @@ -1977,6 +1977,16 @@ int cpu_register_io_memory(int io_index, return io_index << IO_MEM_SHIFT; } +CPUWriteMemoryFunc **cpu_get_io_memory_write(int io_index) +{ + return io_mem_write[io_index >> IO_MEM_SHIFT]; +} + +CPUReadMemoryFunc **cpu_get_io_memory_read(int io_index) +{ + return io_mem_read[io_index >> IO_MEM_SHIFT]; +} + /* physical memory access (slow version, mainly for debug) */ #if defined(CONFIG_USER_ONLY) void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c index bd2355bae01549cc8109061c5b2be29575d103a5..9d80515196b868c0708dce70723387eac3fcac86 100644 --- a/hw/cirrus_vga.c +++ b/hw/cirrus_vga.c @@ -259,9 +259,6 @@ typedef struct CirrusVGAState { uint8_t *cirrus_srcptr; uint8_t *cirrus_srcptr_end; uint32_t cirrus_srccounter; - uint8_t *cirrus_dstptr; - uint8_t *cirrus_dstptr_end; - uint32_t cirrus_dstcounter; /* hwcursor display state */ int last_hw_cursor_size; int last_hw_cursor_x; @@ -269,6 +266,7 @@ typedef struct CirrusVGAState { int last_hw_cursor_y_start; int last_hw_cursor_y_end; int real_vram_size; /* XXX: suppress that */ + CPUWriteMemoryFunc **cirrus_linear_write; } CirrusVGAState; typedef struct PCICirrusVGAState { @@ -285,7 +283,8 @@ static uint8_t rop_to_index[256]; ***************************************/ -static void cirrus_bitblt_reset(CirrusVGAState * s); +static void cirrus_bitblt_reset(CirrusVGAState *s); +static void cirrus_update_memory_access(CirrusVGAState *s); /*************************************** * @@ -711,9 +710,7 @@ static void cirrus_bitblt_reset(CirrusVGAState * s) s->cirrus_srcptr = &s->cirrus_bltbuf[0]; s->cirrus_srcptr_end = &s->cirrus_bltbuf[0]; s->cirrus_srccounter = 0; - s->cirrus_dstptr = &s->cirrus_bltbuf[0]; - s->cirrus_dstptr_end = &s->cirrus_bltbuf[0]; - s->cirrus_dstcounter = 0; + cirrus_update_memory_access(s); } static int cirrus_bitblt_cputovideo(CirrusVGAState * s) @@ -746,6 +743,7 @@ static int cirrus_bitblt_cputovideo(CirrusVGAState * s) } s->cirrus_srcptr = s->cirrus_bltbuf; s->cirrus_srcptr_end = s->cirrus_bltbuf + s->cirrus_blt_srcpitch; + cirrus_update_memory_access(s); return 1; } @@ -1199,7 +1197,6 @@ cirrus_hook_write_sr(CirrusVGAState * s, unsigned reg_index, int reg_value) case 0x14: // Scratch Register 2 case 0x15: // Scratch Register 3 case 0x16: // Performance Tuning Register - case 0x17: // Configuration Readback and Extended Control case 0x18: // Signature Generator Control case 0x19: // Signature Generator Result case 0x1a: // Signature Generator Result @@ -1214,6 +1211,10 @@ cirrus_hook_write_sr(CirrusVGAState * s, unsigned reg_index, int reg_value) reg_index, reg_value); #endif break; + case 0x17: // Configuration Readback and Extended Control + s->sr[reg_index] = reg_value; + cirrus_update_memory_access(s); + break; default: #ifdef DEBUG_CIRRUS printf("cirrus: outport sr_index %02x, sr_value %02x\n", reg_index, @@ -1348,13 +1349,19 @@ cirrus_hook_write_gr(CirrusVGAState * s, unsigned reg_index, int reg_value) return CIRRUS_HOOK_NOT_HANDLED; case 0x05: // Standard VGA, Cirrus extended mode s->gr[reg_index] = reg_value & 0x7f; + cirrus_update_memory_access(s); break; case 0x09: // bank offset #0 case 0x0A: // bank offset #1 + s->gr[reg_index] = reg_value; + cirrus_update_bank_ptr(s, 0); + cirrus_update_bank_ptr(s, 1); + break; case 0x0B: s->gr[reg_index] = reg_value; cirrus_update_bank_ptr(s, 0); cirrus_update_bank_ptr(s, 1); + cirrus_update_memory_access(s); break; case 0x10: // BGCOLOR 0x0000ff00 case 0x11: // FGCOLOR 0x0000ff00 @@ -2304,6 +2311,36 @@ static CPUWriteMemoryFunc *cirrus_linear_write[3] = { cirrus_linear_writel, }; +static void cirrus_linear_mem_writeb(void *opaque, target_phys_addr_t addr, + uint32_t val) +{ + CirrusVGAState *s = (CirrusVGAState *) opaque; + + addr &= s->cirrus_addr_mask; + *(s->vram_ptr + addr) = val; + cpu_physical_memory_set_dirty(s->vram_offset + addr); +} + +static void cirrus_linear_mem_writew(void *opaque, target_phys_addr_t addr, + uint32_t val) +{ + CirrusVGAState *s = (CirrusVGAState *) opaque; + + addr &= s->cirrus_addr_mask; + cpu_to_le16w((uint16_t *)(s->vram_ptr + addr), val); + cpu_physical_memory_set_dirty(s->vram_offset + addr); +} + +static void cirrus_linear_mem_writel(void *opaque, target_phys_addr_t addr, + uint32_t val) +{ + CirrusVGAState *s = (CirrusVGAState *) opaque; + + addr &= s->cirrus_addr_mask; + cpu_to_le32w((uint32_t *)(s->vram_ptr + addr), val); + cpu_physical_memory_set_dirty(s->vram_offset + addr); +} + /*************************************** * * system to screen memory access @@ -2405,6 +2442,37 @@ static CPUWriteMemoryFunc *cirrus_linear_bitblt_write[3] = { cirrus_linear_bitblt_writel, }; +/* Compute the memory access functions */ +static void cirrus_update_memory_access(CirrusVGAState *s) +{ + unsigned mode; + + if ((s->sr[0x17] & 0x44) == 0x44) { + goto generic_io; + } else if (s->cirrus_srcptr != s->cirrus_srcptr_end) { + goto generic_io; + } else { + if ((s->gr[0x0B] & 0x14) == 0x14) { + goto generic_io; + } else if (s->gr[0x0B] & 0x02) { + goto generic_io; + } + + mode = s->gr[0x05] & 0x7; + if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) { + s->cirrus_linear_write[0] = cirrus_linear_mem_writeb; + s->cirrus_linear_write[1] = cirrus_linear_mem_writew; + s->cirrus_linear_write[2] = cirrus_linear_mem_writel; + } else { + generic_io: + s->cirrus_linear_write[0] = cirrus_linear_writeb; + s->cirrus_linear_write[1] = cirrus_linear_writew; + s->cirrus_linear_write[2] = cirrus_linear_writel; + } + } +} + + /* I/O ports */ static uint32_t vga_ioport_read(void *opaque, uint32_t addr) @@ -2933,6 +3001,8 @@ static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci) s->cirrus_linear_io_addr = cpu_register_io_memory(0, cirrus_linear_read, cirrus_linear_write, s); + s->cirrus_linear_write = cpu_get_io_memory_write(s->cirrus_linear_io_addr); + /* I/O handler for LFB */ s->cirrus_linear_bitblt_io_addr = cpu_register_io_memory(0, cirrus_linear_bitblt_read, cirrus_linear_bitblt_write,