The r100 stores a full GPU address in the dst, src, and default
offset registers. For this reason the addresses need to be routed via
the memory controller to obtain offsets. This differs from the r128
which directly stores framebuffer offsets.

Blits outside of VRAM are still not supported. The existing bounds
checks catch this in most cases. A small edge case exists where an
offset register could be set to a low memory address outside of the
VRAM mapping and end up treated as a VRAM offset. This has not been
observed in real drivers but should be handled when implementing
blits outside of VRAM.

Signed-off-by: Chad Jablonski <[email protected]>
---
 hw/display/ati_2d.c | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/hw/display/ati_2d.c b/hw/display/ati_2d.c
index f51ecb747a..e1cbf9efa9 100644
--- a/hw/display/ati_2d.c
+++ b/hw/display/ati_2d.c
@@ -135,10 +135,13 @@ static void setup_2d_blt_ctx(ATIVGAState *s, ATI2DCtx 
*ctx)
         ctx->dst_stride = s->regs.dst_pitch * ctx->bpp;
         ctx->dst_offset = s->regs.dst_offset;
     } else {
+        ATIMemRoute res = ati_mc_route(s, s->regs.dp_gui_master_cntl &
+                                       GMC_DST_PITCH_OFFSET_CNTL
+                                       ? s->regs.dst_offset
+                                       : s->regs.default_offset);
         ctx->dst_stride = s->regs.dp_gui_master_cntl & 
GMC_DST_PITCH_OFFSET_CNTL
                           ? s->regs.dst_pitch : s->regs.default_pitch;
-        ctx->dst_offset = s->regs.dp_gui_master_cntl & 
GMC_DST_PITCH_OFFSET_CNTL
-                          ? s->regs.dst_offset : s->regs.default_offset;
+        ctx->dst_offset = res.addr;
     }
     ctx->dst_bits = s->vga.vram_ptr + ctx->dst_offset;
 
@@ -150,11 +153,13 @@ static void setup_2d_blt_ctx(ATIVGAState *s, ATI2DCtx 
*ctx)
         ctx->src_stride = s->regs.src_pitch * ctx->bpp;
         ctx->src_bits = s->vga.vram_ptr + s->regs.src_offset;
     } else {
+        uint32_t src = s->regs.dp_gui_master_cntl & GMC_SRC_PITCH_OFFSET_CNTL
+                       ? s->regs.src_offset
+                       : s->regs.default_offset;
+        ATIMemRoute res = ati_mc_route(s, src);
         ctx->src_stride = s->regs.dp_gui_master_cntl & 
GMC_SRC_PITCH_OFFSET_CNTL
                           ? s->regs.src_pitch : s->regs.default_pitch;
-        ctx->src_bits = s->vga.vram_ptr +
-                        (s->regs.dp_gui_master_cntl & GMC_SRC_PITCH_OFFSET_CNTL
-                        ? s->regs.src_offset : s->regs.default_offset);
+        ctx->src_bits = s->vga.vram_ptr + res.addr;
     }
     DPRINTF("%d %d %d, %d %d %d, (%d,%d) -> (%d,%d) %dx%d %c %c\n",
             s->regs.src_offset, s->regs.dst_offset, s->regs.default_offset,
-- 
2.54.0


Reply via email to