Drivers for the r100 submit packets using the ring buffer. The real CP engine operates asynchronously. This is a synchronous implementation of it. Packet processing is triggered by a write to CP_RB_WPTR and proceeds until the buffer has been emptied.
Signed-off-by: Chad Jablonski <[email protected]> --- hw/display/ati.c | 50 +++++++++++++++++++++++++++++++++++++++++++ hw/display/ati_int.h | 5 +++++ hw/display/ati_regs.h | 5 +++++ 3 files changed, 60 insertions(+) diff --git a/hw/display/ati.c b/hw/display/ati.c index ad32965866..d758e652b5 100644 --- a/hw/display/ati.c +++ b/hw/display/ati.c @@ -606,6 +606,23 @@ static uint64_t ati_mm_read(void *opaque, hwaddr addr, unsigned int size) case MC_FB_LOCATION: val = s->regs.mc_fb_location; break; + case CP_CSQ_CNTL: + if (s->dev_id == PCI_DEVICE_ID_ATI_RADEON_QY) { + val = s->regs.cp_csq_cntl; + } + break; + case CP_RB_BASE: + val = s->regs.cp_rb_base; + break; + case CP_RB_CNTL: + val = s->regs.cp_rb_cntl; + break; + case CP_RB_RPTR: + val = s->regs.cp_rb_rptr; + break; + case CP_RB_WPTR: + val = s->regs.cp_rb_wptr; + break; default: break; } @@ -1129,6 +1146,35 @@ void ati_mm_write(void *opaque, hwaddr addr, */ s->regs.mc_fb_location = (data & 0xffc0ffc0) | 0x003f0000; break; + case CP_CSQ_CNTL: + if (s->dev_id == PCI_DEVICE_ID_ATI_RADEON_QY) { + s->regs.cp_csq_cntl = data & 0xf0000000; + } + break; + case CP_RB_BASE: + s->regs.cp_rb_base = data & 0xfffffffc; + break; + case CP_RB_CNTL: + s->regs.cp_rb_cntl = data & 0x880f3f3f; + break; + case CP_RB_WPTR: + { + uint32_t size_l2qw = s->regs.cp_rb_cntl & 0x3f; + /* + * RPTR and WPTR are only 23 bits wide, sizes larger + * than this make no sense. + */ + unsigned shift = size_l2qw > 22 ? 23 : size_l2qw + 1; + uint32_t size_msk = (1U << shift) - 1; + s->regs.cp_rb_wptr = data & size_msk; + while (s->regs.cp_rb_rptr != s->regs.cp_rb_wptr) { + uint32_t offs = s->regs.cp_rb_base + + s->regs.cp_rb_rptr * sizeof(uint32_t); + ati_pkt_receive_data(s, &s->cur_packet, ati_mc_read(s, offs)); + s->regs.cp_rb_rptr = (s->regs.cp_rb_rptr + 1) & size_msk; + } + break; + } default: break; } @@ -1251,6 +1297,10 @@ static void ati_vga_reset(DeviceState *dev) s->host_data.next = 0; s->host_data.row = 0; s->host_data.col = 0; + s->regs.cp_rb_rptr = 0; + s->regs.cp_rb_wptr = 0; + s->regs.cp_rb_base = 0; + s->regs.cp_rb_cntl = 0; memset(&s->cur_packet, 0, sizeof(s->cur_packet)); } diff --git a/hw/display/ati_int.h b/hw/display/ati_int.h index bbc360b636..00fb03c4b4 100644 --- a/hw/display/ati_int.h +++ b/hw/display/ati_int.h @@ -124,6 +124,11 @@ typedef struct ATIVGARegs { uint32_t aic_lo_addr; uint32_t aic_hi_addr; uint32_t mc_fb_location; + uint32_t cp_csq_cntl; + uint32_t cp_rb_base; + uint32_t cp_rb_cntl; + uint32_t cp_rb_rptr; + uint32_t cp_rb_wptr; } ATIVGARegs; typedef struct ATIHostDataState { diff --git a/hw/display/ati_regs.h b/hw/display/ati_regs.h index 5e9396bd7a..755b9656b1 100644 --- a/hw/display/ati_regs.h +++ b/hw/display/ati_regs.h @@ -117,11 +117,15 @@ #define OV0_SCALE_CNTL 0x0420 #define SUBPIC_CNTL 0x0540 #define PM4_BUFFER_OFFSET 0x0700 +#define CP_RB_BASE 0x0700 #define PM4_BUFFER_CNTL 0x0704 +#define CP_RB_CNTL 0x0704 #define PM4_BUFFER_WM_CNTL 0x0708 #define PM4_BUFFER_DL_RPTR_ADDR 0x070c #define PM4_BUFFER_DL_RPTR 0x0710 +#define CP_RB_RPTR 0x0710 #define PM4_BUFFER_DL_WPTR 0x0714 +#define CP_RB_WPTR 0x0714 #define PM4_VC_FPU_SETUP 0x071c #define PM4_FPU_CNTL 0x0720 #define PM4_VC_FORMAT 0x0724 @@ -132,6 +136,7 @@ #define PM4_IW_INDOFF 0x0738 #define PM4_IW_INDSIZE 0x073c #define PM4_FPU_FPX0 0x0740 +#define CP_CSQ_CNTL 0x0740 #define PM4_FPU_FPY0 0x0744 #define PM4_FPU_FPX1 0x0748 #define PM4_FPU_FPY1 0x074c -- 2.54.0
