Voodoo: Implement missing AGP CMDFIFO features
Note that the reproduction cases for command 6 currently appear to be a result of CMDFIFO corruption instead of actual usage.
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
#ifndef VIDEO_VOODOO_BANSHEE_H
|
||||
#define VIDEO_VOODOO_BANSHEE_H
|
||||
|
||||
void banshee_cmd_write(void *priv, uint32_t addr, uint32_t val);
|
||||
void banshee_set_overlay_addr(void *priv, uint32_t addr);
|
||||
|
||||
#endif /*VIDEO_VOODOO_BANSHEE_H*/
|
||||
|
||||
@@ -420,6 +420,7 @@ typedef struct voodoo_t {
|
||||
int cmdfifo_rp;
|
||||
int cmdfifo_ret_addr;
|
||||
int cmdfifo_in_sub;
|
||||
int cmdfifo_in_agp;
|
||||
atomic_int cmdfifo_depth_rd;
|
||||
atomic_int cmdfifo_depth_wr;
|
||||
atomic_int cmdfifo_enabled;
|
||||
@@ -433,6 +434,7 @@ typedef struct voodoo_t {
|
||||
int cmdfifo_rp_2;
|
||||
int cmdfifo_ret_addr_2;
|
||||
int cmdfifo_in_sub_2;
|
||||
int cmdfifo_in_agp_2;
|
||||
atomic_int cmdfifo_depth_rd_2;
|
||||
atomic_int cmdfifo_depth_wr_2;
|
||||
atomic_int cmdfifo_enabled_2;
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <86box/device.h>
|
||||
#include <86box/io.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/dma.h>
|
||||
#include <86box/pci.h>
|
||||
#include <86box/rom.h>
|
||||
#include <86box/timer.h>
|
||||
@@ -43,9 +44,11 @@
|
||||
#include <86box/vid_svga_render.h>
|
||||
#include <86box/vid_voodoo_common.h>
|
||||
#include <86box/vid_voodoo_display.h>
|
||||
#include <86box/vid_voodoo_fb.h>
|
||||
#include <86box/vid_voodoo_fifo.h>
|
||||
#include <86box/vid_voodoo_regs.h>
|
||||
#include <86box/vid_voodoo_render.h>
|
||||
#include <86box/vid_voodoo_texture.h>
|
||||
|
||||
#define ROM_BANSHEE "roms/video/voodoo/Pci_sg.rom"
|
||||
#define ROM_CREATIVE_BANSHEE "roms/video/voodoo/BlasterPCI.rom"
|
||||
@@ -220,6 +223,7 @@ enum {
|
||||
Agp_agpHostAddressHigh = 0x08,
|
||||
Agp_agpGraphicsAddress = 0x0C,
|
||||
Agp_agpGraphicsStride = 0x10,
|
||||
Agp_agpMoveCMD = 0x14,
|
||||
};
|
||||
|
||||
#define VGAINIT0_RAMDAC_8BIT (1 << 2)
|
||||
@@ -1365,6 +1369,10 @@ banshee_cmd_read(banshee_t *banshee, uint32_t addr)
|
||||
|
||||
case cmdBaseSize0:
|
||||
ret = voodoo->cmdfifo_size;
|
||||
if (voodoo->cmdfifo_enabled)
|
||||
ret |= 0x100;
|
||||
if (voodoo->cmdfifo_in_agp)
|
||||
ret |= 0x200;
|
||||
break;
|
||||
|
||||
case cmdBaseAddr1:
|
||||
@@ -1394,6 +1402,10 @@ banshee_cmd_read(banshee_t *banshee, uint32_t addr)
|
||||
|
||||
case cmdBaseSize1:
|
||||
ret = voodoo->cmdfifo_size_2;
|
||||
if (voodoo->cmdfifo_enabled_2)
|
||||
ret |= 0x100;
|
||||
if (voodoo->cmdfifo_in_agp_2)
|
||||
ret |= 0x200;
|
||||
break;
|
||||
|
||||
case 0x108:
|
||||
@@ -1613,10 +1625,11 @@ banshee_reg_writew(uint32_t addr, uint16_t val, void *priv)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
banshee_cmd_write(banshee_t *banshee, uint32_t addr, uint32_t val)
|
||||
void
|
||||
banshee_cmd_write(void *priv, uint32_t addr, uint32_t val)
|
||||
{
|
||||
voodoo_t *voodoo = banshee->voodoo;
|
||||
banshee_t *banshee = (banshee_t *) priv;
|
||||
voodoo_t *voodoo = banshee->voodoo;
|
||||
#if 0
|
||||
banshee_log("banshee_cmd_write: addr=%03x val=%08x\n", addr & 0x1fc, val);
|
||||
#endif
|
||||
@@ -1641,6 +1654,62 @@ banshee_cmd_write(banshee_t *banshee, uint32_t addr, uint32_t val)
|
||||
banshee->agpReqSize = val;
|
||||
break;
|
||||
|
||||
case Agp_agpMoveCMD: {
|
||||
uint32_t src_addr = banshee->agpHostAddressLow;
|
||||
uint32_t src_width = banshee->agpHostAddressHigh & 0x3fff;
|
||||
uint32_t src_stride = (banshee->agpHostAddressHigh >> 14) & 0x3fff;
|
||||
uint32_t src_end = src_addr + (banshee->agpReqSize & 0xfffff); /* don't know whether or not stride is accounted for! */
|
||||
uint32_t dest_addr = banshee->agpGraphicsAddress & 0x3ffffff;
|
||||
uint32_t dest_stride = banshee->agpGraphicsStride & 0x7fff;
|
||||
#if 0
|
||||
banshee_log("AGP: %d bytes W%d from %08x S%d to %d:%08x S%d\n", src_end - src_addr, src_width, src_addr, src_stride, (val >> 3) & 3, dest_addr, dest_stride);
|
||||
#endif
|
||||
switch ((val >> 3) & 3) {
|
||||
case 0: /*Linear framebuffer (Banshee)*/
|
||||
case 1: /*Planar YUV*/
|
||||
if (voodoo->texture_present[0][(dest_addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT]) {
|
||||
#if 0
|
||||
banshee_log("texture_present at %08x %i\n", dest_addr, (dest_addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT);
|
||||
#endif
|
||||
flush_texture_cache(voodoo, dest_addr & voodoo->texture_mask, 0);
|
||||
}
|
||||
if (voodoo->texture_present[1][(dest_addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT]) {
|
||||
#if 0
|
||||
banshee_log("texture_present at %08x %i\n", dest_addr, (dest_addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT);
|
||||
#endif
|
||||
flush_texture_cache(voodoo, dest_addr & voodoo->texture_mask, 1);
|
||||
}
|
||||
while ((src_addr < src_end) && (dest_addr <= voodoo->fb_mask)) {
|
||||
dma_bm_read(src_addr, &voodoo->fb_mem[dest_addr], MIN(src_width, voodoo->fb_mask - dest_addr), 4);
|
||||
src_addr += src_stride;
|
||||
dest_addr += dest_stride;
|
||||
}
|
||||
break;
|
||||
case 2: /*Framebuffer*/
|
||||
src_width &= ~3;
|
||||
while (src_addr < src_end) {
|
||||
for (uint32_t i = 0; i < src_width; i += 4)
|
||||
voodoo_fb_writel(dest_addr + i, mem_readl_phys(src_addr + i), voodoo);
|
||||
src_addr += src_stride;
|
||||
dest_addr += dest_stride;
|
||||
}
|
||||
break;
|
||||
case 3: /*Texture*/
|
||||
src_width &= ~3;
|
||||
while (src_addr < src_end) {
|
||||
for (uint32_t i = 0; i < src_width; i += 4)
|
||||
voodoo_tex_writel(dest_addr + i, mem_readl_phys(src_addr + i), voodoo);
|
||||
src_addr += src_stride;
|
||||
dest_addr += dest_stride;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case cmdBaseAddr0:
|
||||
voodoo->cmdfifo_base = (val & 0xfff) << 12;
|
||||
voodoo->cmdfifo_end = voodoo->cmdfifo_base + (((voodoo->cmdfifo_size & 0xff) + 1) << 12);
|
||||
@@ -1655,6 +1724,7 @@ banshee_cmd_write(banshee_t *banshee, uint32_t addr, uint32_t val)
|
||||
voodoo->cmdfifo_enabled = val & 0x100;
|
||||
if (!voodoo->cmdfifo_enabled)
|
||||
voodoo->cmdfifo_in_sub = 0; /*Not sure exactly when this should be reset*/
|
||||
voodoo->cmdfifo_in_agp = val & 0x200;
|
||||
#if 0
|
||||
banshee_log("cmdfifo_base=%08x cmdfifo_end=%08x\n", voodoo->cmdfifo_base, voodoo->cmdfifo_end);
|
||||
#endif
|
||||
@@ -1694,6 +1764,7 @@ banshee_cmd_write(banshee_t *banshee, uint32_t addr, uint32_t val)
|
||||
voodoo->cmdfifo_enabled_2 = val & 0x100;
|
||||
if (!voodoo->cmdfifo_enabled_2)
|
||||
voodoo->cmdfifo_in_sub_2 = 0; /*Not sure exactly when this should be reset*/
|
||||
voodoo->cmdfifo_in_agp_2 = val & 0x200;
|
||||
#if 0
|
||||
banshee_log("cmdfifo_base=%08x cmdfifo_end=%08x\n", voodoo->cmdfifo_base, voodoo->cmdfifo_end);
|
||||
#endif
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include <86box/video.h>
|
||||
#include <86box/vid_svga.h>
|
||||
#include <86box/vid_voodoo_common.h>
|
||||
#include <86box/vid_voodoo_banshee.h>
|
||||
#include <86box/vid_voodoo_banshee_blitter.h>
|
||||
#include <86box/vid_voodoo_fb.h>
|
||||
#include <86box/vid_voodoo_fifo.h>
|
||||
@@ -166,7 +167,10 @@ cmdfifo_get(voodoo_t *voodoo)
|
||||
}
|
||||
}
|
||||
|
||||
val = *(uint32_t *) &voodoo->fb_mem[voodoo->cmdfifo_rp & voodoo->fb_mask];
|
||||
if (voodoo->cmdfifo_in_agp)
|
||||
val = mem_readl_phys(voodoo->cmdfifo_rp);
|
||||
else
|
||||
val = *(uint32_t *) &voodoo->fb_mem[voodoo->cmdfifo_rp & voodoo->fb_mask];
|
||||
|
||||
if (!voodoo->cmdfifo_in_sub)
|
||||
voodoo->cmdfifo_depth_rd++;
|
||||
@@ -200,7 +204,10 @@ cmdfifo_get_2(voodoo_t *voodoo)
|
||||
}
|
||||
}
|
||||
|
||||
val = *(uint32_t *) &voodoo->fb_mem[voodoo->cmdfifo_rp_2 & voodoo->fb_mask];
|
||||
if (voodoo->cmdfifo_in_agp_2)
|
||||
val = mem_readl_phys(voodoo->cmdfifo_rp_2);
|
||||
else
|
||||
val = *(uint32_t *) &voodoo->fb_mem[voodoo->cmdfifo_rp_2 & voodoo->fb_mask];
|
||||
|
||||
if (!voodoo->cmdfifo_in_sub_2)
|
||||
voodoo->cmdfifo_depth_rd_2++;
|
||||
@@ -362,9 +369,21 @@ voodoo_fifo_thread(void *param)
|
||||
break;
|
||||
|
||||
case 3: /*JMP local frame buffer*/
|
||||
voodoo->cmdfifo_rp = (header >> 4) & 0xfffffc;
|
||||
voodoo->cmdfifo_rp = (header >> 4) & 0xfffffc;
|
||||
voodoo->cmdfifo_in_agp = 0;
|
||||
#if 0
|
||||
voodoo_fifo_log("JMP to %08x %04x\n", voodoo->cmdfifo_rp, header);
|
||||
voodoo_fifo_log("JMP LFB to %08x %04x\n", voodoo->cmdfifo_rp, header);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 4: /*JMP AGP*/
|
||||
if (UNLIKELY(voodoo->type < VOODOO_BANSHEE))
|
||||
fatal("CMDFIFO0: Not Banshee %08x\n", header);
|
||||
|
||||
voodoo->cmdfifo_rp = ((header >> 4) & 0x1fffffc) | (cmdfifo_get(voodoo) << 25);
|
||||
voodoo->cmdfifo_in_agp = 1;
|
||||
#if 0
|
||||
voodoo_fifo_log("JMP AGP to %08x %04x\n", voodoo->cmdfifo_rp, header);
|
||||
#endif
|
||||
break;
|
||||
|
||||
@@ -573,6 +592,23 @@ voodoo_fifo_thread(void *param)
|
||||
}
|
||||
break;
|
||||
|
||||
case 6:
|
||||
if (UNLIKELY(voodoo->type < VOODOO_BANSHEE)) {
|
||||
fatal("CMDFIFO6: Not Banshee %08x %08x\n", header, voodoo->cmdfifo_rp);
|
||||
} else {
|
||||
uint32_t val = cmdfifo_get(voodoo);
|
||||
banshee_cmd_write(voodoo->priv, 0x00, val >> 5); /* agpReqSize */
|
||||
banshee_cmd_write(voodoo->priv, 0x04, cmdfifo_get(voodoo)); /* agpHostAddressLow */
|
||||
banshee_cmd_write(voodoo->priv, 0x08, cmdfifo_get(voodoo)); /* agpHostAddressHigh */
|
||||
banshee_cmd_write(voodoo->priv, 0x0c, cmdfifo_get(voodoo)); /* agpGraphicsAddress */
|
||||
banshee_cmd_write(voodoo->priv, 0x10, cmdfifo_get(voodoo)); /* agpGraphicsStride */
|
||||
banshee_cmd_write(voodoo->priv, 0x14, (val & 0x18) | 0x00); /* agpMoveCMD - start transfer */
|
||||
#if 0
|
||||
voodoo_fifo_log("CMDFIFO6 addr=%08x num=%i\n", addr, banshee->agpReqSize);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
fatal("Bad CMDFIFO packet %08x %08x\n", header, voodoo->cmdfifo_rp);
|
||||
}
|
||||
@@ -624,9 +660,21 @@ voodoo_fifo_thread(void *param)
|
||||
break;
|
||||
|
||||
case 3: /*JMP local frame buffer*/
|
||||
voodoo->cmdfifo_rp_2 = (header >> 4) & 0xfffffc;
|
||||
voodoo->cmdfifo_rp_2 = (header >> 4) & 0xfffffc;
|
||||
voodoo->cmdfifo_in_agp_2 = 0;
|
||||
#if 0
|
||||
voodoo_fifo_log("JMP to %08x %04x\n", voodoo->cmdfifo_rp, header);
|
||||
voodoo_fifo_log("JMP LFB to %08x %04x\n", voodoo->cmdfifo_rp_2, header);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 4: /*JMP AGP*/
|
||||
if (UNLIKELY(voodoo->type < VOODOO_BANSHEE))
|
||||
fatal("CMDFIFO0: Not Banshee %08x\n", header);
|
||||
|
||||
voodoo->cmdfifo_rp_2 = ((header >> 4) & 0x1fffffc) | (cmdfifo_get_2(voodoo) << 25);
|
||||
voodoo->cmdfifo_in_agp_2 = 1;
|
||||
#if 0
|
||||
voodoo_fifo_log("JMP AGP to %08x %04x\n", voodoo->cmdfifo_rp_2, header);
|
||||
#endif
|
||||
break;
|
||||
|
||||
@@ -835,6 +883,23 @@ voodoo_fifo_thread(void *param)
|
||||
}
|
||||
break;
|
||||
|
||||
case 6:
|
||||
if (UNLIKELY(voodoo->type < VOODOO_BANSHEE)) {
|
||||
fatal("CMDFIFO6: Not Banshee %08x %08x\n", header, voodoo->cmdfifo_rp);
|
||||
} else {
|
||||
uint32_t val = cmdfifo_get_2(voodoo);
|
||||
banshee_cmd_write(voodoo->priv, 0x00, val >> 5); /* agpReqSize */
|
||||
banshee_cmd_write(voodoo->priv, 0x04, cmdfifo_get_2(voodoo)); /* agpHostAddressLow */
|
||||
banshee_cmd_write(voodoo->priv, 0x08, cmdfifo_get_2(voodoo)); /* agpHostAddressHigh */
|
||||
banshee_cmd_write(voodoo->priv, 0x0c, cmdfifo_get_2(voodoo)); /* agpGraphicsAddress */
|
||||
banshee_cmd_write(voodoo->priv, 0x10, cmdfifo_get_2(voodoo)); /* agpGraphicsStride */
|
||||
banshee_cmd_write(voodoo->priv, 0x14, (val & 0x18) | 0x20); /* agpMoveCMD - start transfer */
|
||||
#if 0
|
||||
voodoo_fifo_log("CMDFIFO6 addr=%08x num=%i\n", addr, banshee->agpReqSize);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
fatal("Bad CMDFIFO packet %08x %08x\n", header, voodoo->cmdfifo_rp);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user