Virge FIFO waiting fixes - slots limit, and undocumented behavior to make Linux work.
This commit is contained in:
@@ -279,6 +279,7 @@ typedef struct virge_t {
|
|||||||
uint32_t dma_ptr;
|
uint32_t dma_ptr;
|
||||||
uint64_t blitter_time;
|
uint64_t blitter_time;
|
||||||
volatile int fifo_slot;
|
volatile int fifo_slot;
|
||||||
|
int fifo_slots_num;
|
||||||
|
|
||||||
pc_timer_t tri_timer;
|
pc_timer_t tri_timer;
|
||||||
|
|
||||||
@@ -1031,6 +1032,8 @@ s3_virge_mmio_fifo_write_l(uint32_t addr, uint32_t val, virge_t *virge)
|
|||||||
else
|
else
|
||||||
s3_virge_bitblt(virge, 32, val);
|
s3_virge_bitblt(virge, 32, val);
|
||||||
} else {
|
} else {
|
||||||
|
if (virge->fifo_slot >= virge->fifo_slots_num)
|
||||||
|
return;
|
||||||
virge->fifo_slot++;
|
virge->fifo_slot++;
|
||||||
switch (addr & 0xfffc) {
|
switch (addr & 0xfffc) {
|
||||||
case 0x8590:
|
case 0x8590:
|
||||||
@@ -1480,16 +1483,25 @@ s3_virge_mmio_read(uint32_t addr, void *priv)
|
|||||||
|
|
||||||
switch (addr & 0xffff) {
|
switch (addr & 0xffff) {
|
||||||
case 0x8505:
|
case 0x8505:
|
||||||
ret = 0;
|
ret = 0xc0;
|
||||||
if (virge->s3d_busy || virge->fifo_slot) {
|
if (!virge->s3d_busy && !virge->fifo_slot)
|
||||||
ret = 0x10;
|
ret |= 0x20;
|
||||||
} else {
|
|
||||||
ret = 0x30;
|
|
||||||
}
|
|
||||||
if (virge->fifo_slot)
|
if (virge->fifo_slot)
|
||||||
virge->fifo_slot--;
|
virge->fifo_slot--;
|
||||||
|
ret |= (virge->fifo_slots_num - virge->fifo_slot);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
case 0x850c:
|
||||||
|
ret = virge->advfunc_cntl & 0x3f;
|
||||||
|
if (virge->fifo_slot)
|
||||||
|
virge->fifo_slot--;
|
||||||
|
ret |= (virge->fifo_slots_num - virge->fifo_slot) << 6;
|
||||||
|
ret &= 0xff;
|
||||||
|
break;
|
||||||
|
case 0x850d:
|
||||||
|
ret = (virge->fifo_slots_num - virge->fifo_slot) >> 2;
|
||||||
|
break;
|
||||||
|
|
||||||
case 0x83b0:
|
case 0x83b0:
|
||||||
case 0x83b1:
|
case 0x83b1:
|
||||||
case 0x83b2:
|
case 0x83b2:
|
||||||
@@ -1564,15 +1576,25 @@ s3_virge_mmio_read_w(uint32_t addr, void *priv)
|
|||||||
|
|
||||||
switch (addr & 0xfffe) {
|
switch (addr & 0xfffe) {
|
||||||
case 0x8504:
|
case 0x8504:
|
||||||
|
ret = 0xc000;
|
||||||
|
if (!virge->s3d_busy && !virge->fifo_slot)
|
||||||
|
ret |= 0x2000;
|
||||||
if (!virge->fifo_slot)
|
if (!virge->fifo_slot)
|
||||||
virge->subsys_stat |= INT_FIFO_EMP;
|
virge->subsys_stat |= INT_FIFO_EMP;
|
||||||
ret |= virge->subsys_stat;
|
ret |= virge->subsys_stat;
|
||||||
if (virge->fifo_slot)
|
if (virge->fifo_slot)
|
||||||
virge->fifo_slot--;
|
virge->fifo_slot--;
|
||||||
ret |= 0x30; /*A bit of a workaround at the moment.*/
|
ret |= (virge->fifo_slots_num - virge->fifo_slot) << 8;
|
||||||
s3_virge_update_irqs(virge);
|
s3_virge_update_irqs(virge);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
case 0x850c:
|
||||||
|
ret = virge->advfunc_cntl & 0x3f;
|
||||||
|
if (virge->fifo_slot)
|
||||||
|
virge->fifo_slot--;
|
||||||
|
ret |= (virge->fifo_slots_num - virge->fifo_slot) << 6;
|
||||||
|
break;
|
||||||
|
|
||||||
case 0x859c:
|
case 0x859c:
|
||||||
return virge->cmd_dma;
|
return virge->cmd_dma;
|
||||||
|
|
||||||
@@ -1660,10 +1682,9 @@ s3_virge_mmio_read_l(uint32_t addr, void *priv)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x8504:
|
case 0x8504:
|
||||||
if (virge->s3d_busy || virge->fifo_slot) {
|
ret = 0x0000c000;
|
||||||
ret = (0x10 << 8);
|
if (!virge->s3d_busy && !virge->fifo_slot) {
|
||||||
} else {
|
ret |= 0x00002000;
|
||||||
ret = (0x10 << 8) | (1 << 13);
|
|
||||||
if (!virge->s3d_busy)
|
if (!virge->s3d_busy)
|
||||||
virge->subsys_stat |= INT_3DF_EMP;
|
virge->subsys_stat |= INT_3DF_EMP;
|
||||||
if (!virge->fifo_slot)
|
if (!virge->fifo_slot)
|
||||||
@@ -1672,9 +1693,17 @@ s3_virge_mmio_read_l(uint32_t addr, void *priv)
|
|||||||
ret |= virge->subsys_stat;
|
ret |= virge->subsys_stat;
|
||||||
if (virge->fifo_slot)
|
if (virge->fifo_slot)
|
||||||
virge->fifo_slot--;
|
virge->fifo_slot--;
|
||||||
|
ret |= (virge->fifo_slots_num - virge->fifo_slot) << 8;
|
||||||
s3_virge_update_irqs(virge);
|
s3_virge_update_irqs(virge);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 0x850c:
|
||||||
|
ret = virge->advfunc_cntl & 0x3f;
|
||||||
|
if (virge->fifo_slot)
|
||||||
|
virge->fifo_slot--;
|
||||||
|
ret |= (virge->fifo_slots_num - virge->fifo_slot) << 6;
|
||||||
|
break;
|
||||||
|
|
||||||
case 0x8590:
|
case 0x8590:
|
||||||
ret = virge->cmd_dma_base;
|
ret = virge->cmd_dma_base;
|
||||||
break;
|
break;
|
||||||
@@ -3498,26 +3527,41 @@ s3_virge_hwcursor_draw(svga_t *svga, int displine)
|
|||||||
svga->hwcursor_latch.addr += 16;
|
svga->hwcursor_latch.addr += 16;
|
||||||
|
|
||||||
switch (svga->bpp) {
|
switch (svga->bpp) {
|
||||||
|
default:
|
||||||
|
if (virge->chip != S3_VIRGEGX2) {
|
||||||
|
fg = svga->pallook[virge->hwc_fg_col & 0xff];
|
||||||
|
bg = svga->pallook[virge->hwc_bg_col & 0xff];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#ifdef FALLTHROUGH_ANNOTATION
|
||||||
|
[[fallthrough]];
|
||||||
|
#endif
|
||||||
|
|
||||||
case 15:
|
case 15:
|
||||||
fg = video_15to32[virge->hwc_fg_col & 0xffff];
|
if (virge->chip != S3_VIRGEGX2) {
|
||||||
bg = video_15to32[virge->hwc_bg_col & 0xffff];
|
fg = video_15to32[virge->hwc_fg_col & 0xffff];
|
||||||
break;
|
bg = video_15to32[virge->hwc_bg_col & 0xffff];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#ifdef FALLTHROUGH_ANNOTATION
|
||||||
|
[[fallthrough]];
|
||||||
|
#endif
|
||||||
|
|
||||||
case 16:
|
case 16:
|
||||||
fg = video_16to32[virge->hwc_fg_col & 0xffff];
|
if (virge->chip != S3_VIRGEGX2) {
|
||||||
bg = video_16to32[virge->hwc_bg_col & 0xffff];
|
fg = video_16to32[virge->hwc_fg_col & 0xffff];
|
||||||
break;
|
bg = video_16to32[virge->hwc_bg_col & 0xffff];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#ifdef FALLTHROUGH_ANNOTATION
|
||||||
|
[[fallthrough]];
|
||||||
|
#endif
|
||||||
|
|
||||||
case 24:
|
case 24:
|
||||||
case 32:
|
case 32:
|
||||||
fg = virge->hwc_fg_col;
|
fg = virge->hwc_fg_col;
|
||||||
bg = virge->hwc_bg_col;
|
bg = virge->hwc_bg_col;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
|
||||||
fg = svga->pallook[virge->hwc_fg_col & 0xff];
|
|
||||||
bg = svga->pallook[virge->hwc_bg_col & 0xff];
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint8_t x = 0; x < 64; x += 16) {
|
for (uint8_t x = 0; x < 64; x += 16) {
|
||||||
@@ -3527,6 +3571,9 @@ s3_virge_hwcursor_draw(svga_t *svga, int displine)
|
|||||||
/*X11*/
|
/*X11*/
|
||||||
for (xx = 0; xx < 16; xx++) {
|
for (xx = 0; xx < 16; xx++) {
|
||||||
if (offset >= 0) {
|
if (offset >= 0) {
|
||||||
|
if (virge->chip == S3_VIRGEGX2)
|
||||||
|
dat[0] ^= 0x8000;
|
||||||
|
|
||||||
if (dat[0] & 0x8000)
|
if (dat[0] & 0x8000)
|
||||||
buffer32->line[displine][offset + svga->x_add] = (dat[1] & 0x8000) ? fg : bg;
|
buffer32->line[displine][offset + svga->x_add] = (dat[1] & 0x8000) ? fg : bg;
|
||||||
}
|
}
|
||||||
@@ -4086,24 +4133,29 @@ s3_virge_reset(void *priv)
|
|||||||
switch (virge->local) {
|
switch (virge->local) {
|
||||||
case S3_VIRGE_325:
|
case S3_VIRGE_325:
|
||||||
case S3_DIAMOND_STEALTH3D_2000:
|
case S3_DIAMOND_STEALTH3D_2000:
|
||||||
|
virge->fifo_slots_num = 8;
|
||||||
virge->svga.crtc[0x59] = 0x70;
|
virge->svga.crtc[0x59] = 0x70;
|
||||||
break;
|
break;
|
||||||
case S3_DIAMOND_STEALTH3D_3000:
|
case S3_DIAMOND_STEALTH3D_3000:
|
||||||
case S3_STB_VELOCITY_3D:
|
case S3_STB_VELOCITY_3D:
|
||||||
|
virge->fifo_slots_num = 8;
|
||||||
virge->svga.crtc[0x59] = 0x70;
|
virge->svga.crtc[0x59] = 0x70;
|
||||||
break;
|
break;
|
||||||
case S3_VIRGE_GX2:
|
case S3_VIRGE_GX2:
|
||||||
case S3_DIAMOND_STEALTH3D_4000:
|
case S3_DIAMOND_STEALTH3D_4000:
|
||||||
|
virge->fifo_slots_num = 16;
|
||||||
virge->svga.crtc[0x6c] = 1;
|
virge->svga.crtc[0x6c] = 1;
|
||||||
virge->svga.crtc[0x59] = 0x70;
|
virge->svga.crtc[0x59] = 0x70;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case S3_TRIO_3D2X:
|
case S3_TRIO_3D2X:
|
||||||
|
virge->fifo_slots_num = 16;
|
||||||
virge->svga.crtc[0x6c] = 1;
|
virge->svga.crtc[0x6c] = 1;
|
||||||
virge->svga.crtc[0x59] = 0x70;
|
virge->svga.crtc[0x59] = 0x70;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
virge->fifo_slots_num = 8;
|
||||||
virge->svga.crtc[0x6c] = 1;
|
virge->svga.crtc[0x6c] = 1;
|
||||||
virge->svga.crtc[0x59] = 0x70;
|
virge->svga.crtc[0x59] = 0x70;
|
||||||
break;
|
break;
|
||||||
@@ -4262,6 +4314,7 @@ s3_virge_init(const device_t *info)
|
|||||||
switch (info->local) {
|
switch (info->local) {
|
||||||
case S3_VIRGE_325:
|
case S3_VIRGE_325:
|
||||||
case S3_DIAMOND_STEALTH3D_2000:
|
case S3_DIAMOND_STEALTH3D_2000:
|
||||||
|
virge->fifo_slots_num = 8;
|
||||||
virge->svga.decode_mask = (4 << 20) - 1;
|
virge->svga.decode_mask = (4 << 20) - 1;
|
||||||
virge->virge_id_high = 0x56;
|
virge->virge_id_high = 0x56;
|
||||||
virge->virge_id_low = 0x31;
|
virge->virge_id_low = 0x31;
|
||||||
@@ -4271,6 +4324,7 @@ s3_virge_init(const device_t *info)
|
|||||||
break;
|
break;
|
||||||
case S3_DIAMOND_STEALTH3D_3000:
|
case S3_DIAMOND_STEALTH3D_3000:
|
||||||
case S3_STB_VELOCITY_3D:
|
case S3_STB_VELOCITY_3D:
|
||||||
|
virge->fifo_slots_num = 8;
|
||||||
virge->svga.decode_mask = (8 << 20) - 1;
|
virge->svga.decode_mask = (8 << 20) - 1;
|
||||||
virge->virge_id_high = 0x88;
|
virge->virge_id_high = 0x88;
|
||||||
virge->virge_id_low = 0x3d;
|
virge->virge_id_low = 0x3d;
|
||||||
@@ -4280,6 +4334,7 @@ s3_virge_init(const device_t *info)
|
|||||||
break;
|
break;
|
||||||
case S3_VIRGE_GX2:
|
case S3_VIRGE_GX2:
|
||||||
case S3_DIAMOND_STEALTH3D_4000:
|
case S3_DIAMOND_STEALTH3D_4000:
|
||||||
|
virge->fifo_slots_num = 16;
|
||||||
virge->svga.decode_mask = (4 << 20) - 1;
|
virge->svga.decode_mask = (4 << 20) - 1;
|
||||||
virge->virge_id_high = 0x8a;
|
virge->virge_id_high = 0x8a;
|
||||||
virge->virge_id_low = 0x10;
|
virge->virge_id_low = 0x10;
|
||||||
@@ -4291,6 +4346,7 @@ s3_virge_init(const device_t *info)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case S3_TRIO_3D2X:
|
case S3_TRIO_3D2X:
|
||||||
|
virge->fifo_slots_num = 16;
|
||||||
virge->svga.decode_mask = (8 << 20) - 1;
|
virge->svga.decode_mask = (8 << 20) - 1;
|
||||||
virge->virge_id_high = 0x8a;
|
virge->virge_id_high = 0x8a;
|
||||||
virge->virge_id_low = 0x13;
|
virge->virge_id_low = 0x13;
|
||||||
@@ -4309,6 +4365,7 @@ s3_virge_init(const device_t *info)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
virge->fifo_slots_num = 8;
|
||||||
virge->svga.decode_mask = (4 << 20) - 1;
|
virge->svga.decode_mask = (4 << 20) - 1;
|
||||||
virge->virge_id_high = 0x8a;
|
virge->virge_id_high = 0x8a;
|
||||||
virge->virge_id_low = 0x01;
|
virge->virge_id_low = 0x01;
|
||||||
|
Reference in New Issue
Block a user