Add AGP GART implementation

This commit is contained in:
RichardG867
2021-11-10 21:14:54 -03:00
parent d65cfe1f50
commit 724accd167
7 changed files with 322 additions and 68 deletions

View File

@@ -29,6 +29,7 @@
#include <86box/chipset.h>
#include <86box/spd.h>
#include <86box/machine.h>
#include <86box/video.h>
enum
@@ -57,6 +58,7 @@ typedef struct
uint8_t regs[256], regs_locked[256];
int type;
smram_t *smram_low, *smram_high;
void *agpgart;
} i4x0_t;
@@ -208,14 +210,25 @@ i4x0_smram_handler_phase1(i4x0_t *dev)
static void
i4x0_mask_bar(uint8_t *regs)
i4x0_mask_bar(uint8_t *regs, void *agpgart)
{
uint32_t bar;
/* Make sure the aperture's base is aligned to its size. */
bar = (regs[0x13] << 24) | (regs[0x12] << 16);
bar &= (((uint32_t) regs[0xb4] << 22) | 0xf0000000);
regs[0x12] = (bar >> 16) & 0xff;
regs[0x13] = (bar >> 24) & 0xff;
if (!agpgart)
return;
/* Map aperture and GART. */
agpgart_set_aperture(agpgart,
bar,
((uint32_t) (uint8_t) (~regs[0xb4] & 0x3f) + 1) << 22,
!!(regs[0x51] & 0x02));
agpgart_set_gart(agpgart, (regs[0xb9] << 8) | (regs[0xba] << 16) | (regs[0xbb] << 24));
}
@@ -323,7 +336,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
case INTEL_440BX: case INTEL_440ZX:
case INTEL_440GX:
regs[0x12] = (val & 0xc0);
i4x0_mask_bar(regs);
i4x0_mask_bar(regs, dev->agpgart);
break;
}
break;
@@ -333,7 +346,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
case INTEL_440BX: case INTEL_440ZX:
case INTEL_440GX:
regs[0x13] = val;
i4x0_mask_bar(regs);
i4x0_mask_bar(regs, dev->agpgart);
break;
}
break;
@@ -411,15 +424,19 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
break;
case INTEL_440LX:
regs[0x51] = (regs[0x51] & 0x40) | (val & 0x87);
i4x0_mask_bar(regs, dev->agpgart);
break;
case INTEL_440EX:
regs[0x51] = (val & 0x86);
i4x0_mask_bar(regs, dev->agpgart);
break;
case INTEL_440BX: case INTEL_440ZX:
regs[0x51] = (regs[0x51] & 0x70) | (val & 0x8f);
i4x0_mask_bar(regs, dev->agpgart);
break;
case INTEL_440GX:
regs[0x51] = (regs[0x51] & 0xb0) | (val & 0x4f);
i4x0_mask_bar(regs, dev->agpgart);
break;
}
break;
@@ -1074,7 +1091,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
case INTEL_440BX: case INTEL_440ZX:
case INTEL_440GX:
regs[0xb4] = (val & 0x3f);
i4x0_mask_bar(regs);
i4x0_mask_bar(regs, dev->agpgart);
break;
}
break;
@@ -1084,6 +1101,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
case INTEL_440BX: case INTEL_440ZX:
case INTEL_440GX:
regs[0xb9] = (val & 0xf0);
i4x0_mask_bar(regs, dev->agpgart);
break;
}
break;
@@ -1094,6 +1112,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
case INTEL_440BX: case INTEL_440ZX:
case INTEL_440GX:
regs[addr] = val;
i4x0_mask_bar(regs, dev->agpgart);
break;
}
break;
@@ -1593,10 +1612,13 @@ static void
pci_add_card(PCI_ADD_NORTHBRIDGE, i4x0_read, i4x0_write, dev);
if ((dev->type >= INTEL_440BX) && !(regs[0x7a] & 0x02))
if ((dev->type >= INTEL_440BX) && !(regs[0x7a] & 0x02)) {
device_add((dev->type == INTEL_440GX) ? &i440gx_agp_device : &i440bx_agp_device);
else if (dev->type >= INTEL_440LX)
dev->agpgart = device_add(&agpgart_device);
} else if (dev->type >= INTEL_440LX) {
device_add(&i440lx_agp_device);
dev->agpgart = device_add(&agpgart_device);
}
return dev;
}

View File

@@ -33,6 +33,7 @@
#include <86box/pci.h>
#include <86box/chipset.h>
#include <86box/spd.h>
#include <86box/video.h>
#define VIA_585 0x05851000
#define VIA_595 0x05950000
@@ -50,6 +51,7 @@ typedef struct via_apollo_t
uint8_t pci_conf[256];
smram_t *smram;
void *agpgart;
} via_apollo_t;
@@ -86,6 +88,25 @@ apollo_smram_map(via_apollo_t *dev, int smm, uint32_t host_base, uint32_t size,
}
static void
apollo_agp_map(via_apollo_t *dev)
{
/* Make sure the aperture's base is aligned to its size. */
dev->pci_conf[0x12] &= dev->pci_conf[0x84] << 4;
dev->pci_conf[0x13] &= 0xf0 | (dev->pci_conf[0x84] >> 4);
if (!dev->agpgart)
return;
/* Map aperture and GART. */
agpgart_set_aperture(dev->agpgart,
(dev->pci_conf[0x12] << 16) | (dev->pci_conf[0x13] << 24),
((uint32_t) (uint8_t) ~dev->pci_conf[0x84] + 1) << 20,
!!(dev->pci_conf[0x88] & 0x02));
agpgart_set_gart(dev->agpgart, (dev->pci_conf[0x89] << 8) | (dev->pci_conf[0x8a] << 16) | (dev->pci_conf[0x8b] << 24));
}
static void
via_apollo_setup(via_apollo_t *dev)
{
@@ -221,6 +242,8 @@ via_apollo_host_bridge_write(int func, int addr, uint8_t val, void *priv)
((addr >= 0xad) && (addr < 0xf0)) || ((addr >= 0xf8) && (addr < 0xfc)) ||
(addr == 0xfd))
return;
if (((addr == 0x12) || (addr == 0x13)) && (dev->id < VIA_597))
return;
if (((addr == 0x78) || (addr >= 0xad)) && (dev->id == VIA_597))
return;
if (((addr == 0x67) || ((addr >= 0xf0) && (addr < 0xfc))) && (dev->id < VIA_691))
@@ -260,9 +283,11 @@ via_apollo_host_bridge_write(int func, int addr, uint8_t val, void *priv)
break;
case 0x12: /* Graphics Aperture Base */
dev->pci_conf[0x12] = (val & 0xf0);
apollo_agp_map(dev);
break;
case 0x13: /* Graphics Aperture Base */
dev->pci_conf[0x13] = val;
apollo_agp_map(dev);
break;
case 0x50: /* Cache Control 1 */
@@ -580,20 +605,23 @@ via_apollo_host_bridge_write(int func, int addr, uint8_t val, void *priv)
dev->pci_conf[0x84] = val;
else
dev->pci_conf[0x84] = (dev->pci_conf[0x84] & ~0xf0) | (val & 0xf0);
apollo_agp_map(dev);
break;
case 0x88:
if((dev->id == VIA_693A) || (dev->id == VIA_8601))
dev->pci_conf[0x88] = (dev->pci_conf[0x88] & ~0x06) | (val & 0x06);
else
dev->pci_conf[0x88] = (dev->pci_conf[0x88] & ~0x07) | (val & 0x07);
apollo_agp_map(dev);
break;
case 0x89:
dev->pci_conf[0x89] = val & 0xf0;
apollo_agp_map(dev);
break;
case 0x8a:
case 0x8b:
if((dev->id == VIA_693A) || (dev->id == VIA_8601))
dev->pci_conf[addr] = val;
else
dev->pci_conf[0x89] = (dev->pci_conf[0x89] & ~0xf0) | (val & 0xf0);
dev->pci_conf[addr] = val;
apollo_agp_map(dev);
break;
case 0xa8:
@@ -706,6 +734,9 @@ via_apollo_init(const device_t *info)
break;
}
if (dev->id >= VIA_597)
dev->agpgart = device_add(&agpgart_device);
if ((dev->id >= VIA_694) && (dev->id != VIA_8601))
dev->drb_unit = 16;
else if (dev->id >= VIA_597)