Writing to any of the HOST_DATA0-7 registers pushes the written data into a buffer. A final write to HOST_DATA_LAST writes data to the buffer and triggers the pending blit operation.
The buffer for now is a static 4MiB and overflows are checked. This seems like a large enough value given what I've seen in testing. Future work could dynamically size the buffer based on the destination dimensions if needed. This sets things up for implementation of HOST_DATA as a blit operation source in a future patch. Signed-off-by: Chad Jablonski <[email protected]> --- hw/display/ati.c | 15 +++++++++++++++ hw/display/ati_dbg.c | 9 +++++++++ hw/display/ati_int.h | 3 +++ hw/display/ati_regs.h | 9 +++++++++ 4 files changed, 36 insertions(+) diff --git a/hw/display/ati.c b/hw/display/ati.c index 4ff17209c4..0a686750ae 100644 --- a/hw/display/ati.c +++ b/hw/display/ati.c @@ -969,6 +969,20 @@ static void ati_mm_write(void *opaque, hwaddr addr, case SRC_SC_BOTTOM_RIGHT: s->regs.src_sc_bottom_right = data; break; + case HOST_DATA0 ... HOST_DATA7: + case HOST_DATA_LAST: + if (s->host_data_pos + 4 > sizeof(s->host_data_buffer)) { + qemu_log_mask(LOG_UNIMP, "HOST_DATA buffer overflow " + "(buffer size: %zu bytes)\n", + sizeof(s->host_data_buffer)); + return; + } + stn_he_p(&s->host_data_buffer[s->host_data_pos], 4, data); + s->host_data_pos += 4; + if (addr == HOST_DATA_LAST) { + ati_2d_blt(s); + } + break; default: break; } @@ -1074,6 +1088,7 @@ static void ati_vga_reset(DeviceState *dev) /* reset vga */ vga_common_reset(&s->vga); s->mode = VGA_MODE; + s->host_data_pos = 0; } static void ati_vga_exit(PCIDevice *dev) diff --git a/hw/display/ati_dbg.c b/hw/display/ati_dbg.c index 3ffa7f35df..5c799d540a 100644 --- a/hw/display/ati_dbg.c +++ b/hw/display/ati_dbg.c @@ -252,6 +252,15 @@ static struct ati_regdesc ati_reg_names[] = { {"MC_SRC1_CNTL", 0x19D8}, {"TEX_CNTL", 0x1800}, {"RAGE128_MPP_TB_CONFIG", 0x01c0}, + {"HOST_DATA0", 0x17c0}, + {"HOST_DATA1", 0x17c4}, + {"HOST_DATA2", 0x17c8}, + {"HOST_DATA3", 0x17cc}, + {"HOST_DATA4", 0x17d0}, + {"HOST_DATA5", 0x17d4}, + {"HOST_DATA6", 0x17d8}, + {"HOST_DATA7", 0x17dc}, + {"HOST_DATA_LAST", 0x17e0}, {NULL, -1} }; diff --git a/hw/display/ati_int.h b/hw/display/ati_int.h index aab3cbf81a..16e5d29a5a 100644 --- a/hw/display/ati_int.h +++ b/hw/display/ati_int.h @@ -15,6 +15,7 @@ #include "hw/i2c/bitbang_i2c.h" #include "vga_int.h" #include "qom/object.h" +#include "qemu/units.h" /*#define DEBUG_ATI*/ @@ -108,6 +109,8 @@ struct ATIVGAState { MemoryRegion io; MemoryRegion mm; ATIVGARegs regs; + uint32_t host_data_pos; + uint8_t host_data_buffer[4 * MiB]; }; const char *ati_reg_name(int num); diff --git a/hw/display/ati_regs.h b/hw/display/ati_regs.h index 2b56b9fb66..9b52b61dcb 100644 --- a/hw/display/ati_regs.h +++ b/hw/display/ati_regs.h @@ -252,6 +252,15 @@ #define DP_T12_CNTL 0x178c #define DST_BRES_T1_LNTH 0x1790 #define DST_BRES_T2_LNTH 0x1794 +#define HOST_DATA0 0x17c0 +#define HOST_DATA1 0x17c4 +#define HOST_DATA2 0x17c8 +#define HOST_DATA3 0x17cc +#define HOST_DATA4 0x17d0 +#define HOST_DATA5 0x17d4 +#define HOST_DATA6 0x17d8 +#define HOST_DATA7 0x17dc +#define HOST_DATA_LAST 0x17e0 #define SCALE_SRC_HEIGHT_WIDTH 0x1994 #define SCALE_OFFSET_0 0x1998 #define SCALE_PITCH 0x199c -- 2.51.0
