Finished the ALADDiN-PRO II, implemented the Contaq/Cypress 82C596(A) and 82C597 chipsets, added the ASUS P5A, Gigabyte GA-5AX, PC CHIPS M729, and Green-B, removed the "Virtual PC 2007" device as it turns out it was actually SMBus all along, did some fixes to the ALi SMBUS, fixed start LM75 SMBus address and enabled it by default, and added a ASUS P5A-specific version of the Winbond W83781D hardware monitor.

This commit is contained in:
OBattler
2021-07-12 05:56:06 +02:00
parent b674372248
commit dbddb3e309
24 changed files with 1007 additions and 489 deletions

View File

@@ -14,12 +14,12 @@
#
add_library(chipset OBJECT acc2168.c cs8230.c ali1217.c ali1429.c ali1489.c ali1531.c ali1541.c
ali1543.c headland.c intel_82335.c cs4031.c intel_420ex.c intel_4x0.c intel_sio.c intel_piix.c
../ioapic.c neat.c opti283.c opti291.c opti391.c opti495.c opti822.c opti895.c opti5x7.c
scamp.c scat.c sis_85c310.c sis_85c4xx.c sis_85c496.c sis_85c50x.c sis_5511.c sis_5571.c
via_vt82c49x.c via_vt82c505.c sis_85c310.c sis_85c4xx.c sis_85c496.c sis_85c50x.c
gc100.c stpc.c
via_apollo.c via_pipc.c vl82c480.c wd76c10.c)
ali1543.c ali1621.c headland.c intel_82335.c contaq_82c59x.c cs4031.c intel_420ex.c
intel_4x0.c intel_sio.c intel_piix.c ../ioapic.c neat.c opti283.c opti291.c opti391.c
opti495.c opti822.c opti895.c opti5x7.c scamp.c scat.c sis_85c310.c sis_85c4xx.c
sis_85c496.c sis_85c50x.c sis_5511.c sis_5571.c via_vt82c49x.c via_vt82c505.c sis_85c310.c
sis_85c4xx.c sis_85c496.c sis_85c50x.c gc100.c stpc.c via_apollo.c via_pipc.c vl82c480.c
wd76c10.c)
if(I450KX)
target_sources(chipset PRIVATE intel_i450kx.c)

View File

@@ -295,7 +295,6 @@ ali1533_write(int func, int addr, uint8_t val, void *priv)
break;
}
ali1543_log("IDE slot = %02X (A%0i)\n", dev->ide_slot - 5, dev->ide_slot + 11);
pclog("IDE slot = %02X (A%0i)\n", dev->ide_slot - 5, dev->ide_slot + 11);
ali5229_ide_irq_handler(dev);
break;
@@ -365,7 +364,6 @@ ali1533_write(int func, int addr, uint8_t val, void *priv)
break;
}
ali1543_log("PMU slot = %02X (A%0i)\n", dev->pmu_slot - 5, dev->pmu_slot + 11);
pclog("PMU slot = %02X (A%0i)\n", dev->pmu_slot - 5, dev->pmu_slot + 11);
switch (val & 0x03) {
case 0x00:
dev->usb_slot = 0x14; /* A31 = slot 20 */
@@ -381,7 +379,6 @@ ali1533_write(int func, int addr, uint8_t val, void *priv)
break;
}
ali1543_log("USB slot = %02X (A%0i)\n", dev->usb_slot - 5, dev->usb_slot + 11);
pclog("USB slot = %02X (A%0i)\n", dev->usb_slot - 5, dev->usb_slot + 11);
break;
case 0x73: /* DDMA Base Address */
@@ -424,7 +421,7 @@ ali1533_write(int func, int addr, uint8_t val, void *priv)
case 0x78:
if (dev->type == 1) {
pclog("PCI78 = %02X\n", val);
ali1543_log("PCI78 = %02X\n", val);
dev->pci_conf[addr] = val & 0x33;
}
break;
@@ -557,10 +554,10 @@ ali5229_ide_handler(ali1543_t *dev)
{
uint32_t ch = 0;
uint16_t native_base_pri_addr = (dev->ide_conf[0x11] | dev->ide_conf[0x10] << 8);
uint16_t native_side_pri_addr = (dev->ide_conf[0x15] | dev->ide_conf[0x14] << 8);
uint16_t native_base_sec_addr = (dev->ide_conf[0x19] | dev->ide_conf[0x18] << 8);
uint16_t native_side_sec_addr = (dev->ide_conf[0x1c] | dev->ide_conf[0x1b] << 8);
uint16_t native_base_pri_addr = ((dev->ide_conf[0x11] | dev->ide_conf[0x10] << 8)) & 0xfffe;
uint16_t native_side_pri_addr = ((dev->ide_conf[0x15] | dev->ide_conf[0x14] << 8)) & 0xfffe;
uint16_t native_base_sec_addr = ((dev->ide_conf[0x19] | dev->ide_conf[0x18] << 8)) & 0xfffe;
uint16_t native_side_sec_addr = ((dev->ide_conf[0x1c] | dev->ide_conf[0x1b] << 8)) & 0xfffe;
uint16_t comp_base_pri_addr = 0x01f0;
uint16_t comp_side_pri_addr = 0x03f6;
@@ -597,7 +594,7 @@ ali5229_ide_handler(ali1543_t *dev)
if (dev->ide_conf[0x04] & 0x01) {
/* Primary Channel Setup */
if (dev->ide_conf[0x09] & 0x20) {
if ((dev->ide_conf[0x09] & 0x20) || (dev->ide_conf[0x4d] & 0x80)) {
ali1543_log("ali5229_ide_handler(): Primary IDE base now %04X...\n", current_pri_base);
ide_set_base(0, current_pri_base);
ali1543_log("ali5229_ide_handler(): Primary IDE side now %04X...\n", current_pri_side);
@@ -611,7 +608,7 @@ ali5229_ide_handler(ali1543_t *dev)
}
/* Secondary Channel Setup */
if (dev->ide_conf[0x09] & 0x10) {
if ((dev->ide_conf[0x09] & 0x10) || (dev->ide_conf[0x4d] & 0x80)) {
ali1543_log("ali5229_ide_handler(): Secondary IDE base now %04X...\n", current_sec_base);
ide_set_base(1, current_sec_base);
ali1543_log("ali5229_ide_handler(): Secondary IDE side now %04X...\n", current_sec_side);
@@ -650,8 +647,8 @@ ali5229_chip_reset(ali1543_t *dev)
dev->ide_conf[0x15] = 0x03;
dev->ide_conf[0x18] = 0x71;
dev->ide_conf[0x19] = 0x01;
dev->ide_conf[0x1a] = 0x75;
dev->ide_conf[0x1b] = 0x03;
dev->ide_conf[0x1c] = 0x75;
dev->ide_conf[0x1d] = 0x03;
dev->ide_conf[0x20] = 0x01;
dev->ide_conf[0x21] = 0xf0;
dev->ide_conf[0x3d] = 0x01;
@@ -667,12 +664,13 @@ ali5229_chip_reset(ali1543_t *dev)
if (dev->type == 1) {
dev->ide_conf[0x08] = 0xc1;
dev->ide_conf[0x43] = 0x00;
dev->ide_conf[0x4b] = 0x4a;
dev->ide_conf[0x4e] = 0xba;
dev->ide_conf[0x4f] = 0x1a;
}
ali5229_write(0, 0x04, 0x00 /*0x01*/, dev);
ali5229_write(0, 0x04, 0x05, dev);
ali5229_write(0, 0x10, 0xf1, dev);
ali5229_write(0, 0x11, 0x01, dev);
ali5229_write(0, 0x14, 0xf5, dev);
@@ -742,10 +740,12 @@ ali5229_write(int func, int addr, uint8_t val, void *priv)
break;
/* Primary Base Address */
case 0x10: case 0x11: case 0x12: case 0x13: case 0x14:
case 0x10: case 0x11: case 0x14: case 0x15:
/* FALLTHROUGH */
/* Secondary Base Address */
case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c:
case 0x18: case 0x19: case 0x1c: case 0x1d:
/* FALLTHROUGH */
/* Bus Mastering Base Address */
case 0x20: case 0x21: case 0x22: case 0x23:
@@ -779,6 +779,7 @@ ali5229_write(int func, int addr, uint8_t val, void *priv)
case 0x4d:
dev->ide_conf[addr] = val & 0x80;
ali5229_ide_handler(dev);
break;
case 0x4f:
@@ -969,7 +970,7 @@ ali7101_write(int func, int addr, uint8_t val, void *priv)
else if (addr == 0x11)
dev->pmu_conf[addr] = val;
pclog("New ACPI base address: %08X\n", (dev->pmu_conf[0x11] << 8) | (dev->pmu_conf[0x10] & 0xc0));
ali1543_log("New ACPI base address: %08X\n", (dev->pmu_conf[0x11] << 8) | (dev->pmu_conf[0x10] & 0xc0));
acpi_update_io_mapping(dev->acpi, (dev->pmu_conf[0x11] << 8) | (dev->pmu_conf[0x10] & 0xc0), dev->pmu_conf[0x04] & 1);
}
break;
@@ -986,10 +987,10 @@ ali7101_write(int func, int addr, uint8_t val, void *priv)
dev->pmu_conf[addr] = val;
if (dev->type == 1) {
pclog("New SMBUS base address: %08X\n", (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xc0));
ali1543_log("New SMBUS base address: %08X\n", (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xc0));
smbus_ali7101_remap(dev->smbus, (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xc0), (dev->pmu_conf[0xe0] & 1) && (dev->pmu_conf[0x04] & 1));
} else {
pclog("New SMBUS base address: %08X\n", (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xe0));
ali1543_log("New SMBUS base address: %08X\n", (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xe0));
smbus_ali7101_remap(dev->smbus, (dev->pmu_conf[0x15] << 8) | (dev->pmu_conf[0x14] & 0xe0), (dev->pmu_conf[0xe0] & 1) && (dev->pmu_conf[0x04] & 1));
}
}

View File

@@ -36,8 +36,7 @@ typedef struct ali1621_t
{
uint8_t pci_conf[256];
smram_t * smram;
void * agp_bridge;
smram_t * smram[2];
} ali1621_t;
@@ -60,34 +59,80 @@ ali1621_log(const char *fmt, ...)
#endif
/* Table translated to a more sensible format:
Read cycles:
SMREN SMM Mode Code Data
0 X X PCI PCI
1 0 Close PCI PCI
1 0 Lock PCI PCI
1 0 Protect PCI PCI
1 0 Open DRAM DRAM
1 1 Open DRAM DRAM
1 1 Protect DRAM DRAM
1 1 Close DRAM PCI
1 1 Lock DRAM PCI
Write cycles:
SMWEN SMM Mode Data
0 X X PCI
1 0 Close PCI
1 0 Lock PCI
1 0 Protect PCI
1 0 Open DRAM
1 1 Open DRAM
1 1 Protect DRAM
1 1 Close PCI
1 1 Lock PCI
Explanation of the modes based above:
If SM*EN = 0, SMRAM is entirely disabled, otherwise:
If mode is Close or Lock, then SMRAM always goes to PCI outside SMM,
and data to PCI, code to DRAM in SMM;
If mode is Protect, then SMRAM always goes to PCI outside SMM and
DRAM in SMM;
If mode is Open, then SMRAM always goes to DRAM.
Read and write are enabled separately.
*/
static void
ali1621_smram_recalc(uint8_t val, ali1621_t *dev)
{
uint16_t access_smm = 0x0000, access_normal = 0x0000;
smram_disable_all();
if (val & 1) {
switch (val & 0x0c) {
case 0x00:
ali1621_log("SMRAM: D0000 -> B0000 (%i)\n", val & 2);
smram_enable(dev->smram, 0xd0000, 0xb0000, 0x10000, val & 2, 1);
if (val & 0x10)
mem_set_mem_state_smram_ex(1, 0xd0000, 0x10000, 0x02);
break;
case 0x04:
ali1621_log("SMRAM: A0000 -> A0000 (%i)\n", val & 2);
smram_enable(dev->smram, 0xa0000, 0xa0000, 0x20000, val & 2, 1);
if (val & 0x10)
mem_set_mem_state_smram_ex(1, 0xa0000, 0x20000, 0x02);
break;
case 0x08:
ali1621_log("SMRAM: 30000 -> B0000 (%i)\n", val & 2);
smram_enable(dev->smram, 0x30000, 0xb0000, 0x10000, val & 2, 1);
if (val & 0x10)
mem_set_mem_state_smram_ex(1, 0x30000, 0x10000, 0x02);
if (val & 0xc0) {
/* SMRAM 0: A0000-BFFFF */
if (val & 0x80) {
access_smm = ACCESS_SMRAM_X;
switch (val & 0x30) {
case 0x10: /* Open. */
access_normal = ACCESS_SMRAM_RX;
/* FALLTHROUGH */
case 0x30: /* Protect. */
access_smm |= ACCESS_SMRAM_R;
break;
}
}
if (val & 0x40) switch (val & 0x30) {
case 0x10: /* Open. */
access_normal |= ACCESS_SMRAM_W;
/* FALLTHROUGH */
case 0x30: /* Protect. */
access_smm |= ACCESS_SMRAM_W;
break;
}
smram_enable(dev->smram[0], 0xa0000, 0xa0000, 0x20000, ((val & 0x30) == 0x10), (val & 0x30));
mem_set_access(ACCESS_NORMAL, 3, 0xa0000, 0x20000, access_normal);
mem_set_access(ACCESS_SMM, 3, 0xa0000, 0x20000, access_smm);
}
if (val & 0x08)
smram_enable(dev->smram[1], 0x38000, 0xa8000, 0x08000, 0, 1);
flushmmucache_nopc();
}
@@ -95,32 +140,61 @@ ali1621_smram_recalc(uint8_t val, ali1621_t *dev)
static void
ali1621_shadow_recalc(int cur_reg, ali1621_t *dev)
{
int i, bit, r_reg, w_reg;
int i, r_bit, w_bit, reg;
uint32_t base, flags = 0;
shadowbios = shadowbios_write = 0;
for (i = 0; i < 16; i++) {
/* C0000-EFFFF */
for (i = 0; i < 12; i++) {
base = 0x000c0000 + (i << 14);
bit = i & 7;
r_reg = 0x56 + (i >> 3);
w_reg = 0x58 + (i >> 3);
r_bit = (i << 1) + 4;
reg = 0x84;
if (r_bit > 23) {
r_bit &= 7;
reg += 3;
} else if (r_bit > 15) {
r_bit &= 7;
reg += 2;
} else if (r_bit > 7) {
r_bit &= 7;
reg++;
}
w_bit = r_bit + 1;
flags = (dev->pci_conf[r_reg] & (1 << bit)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
flags |= ((dev->pci_conf[w_reg] & (1 << bit)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY);
flags = (dev->pci_conf[reg] & (1 << r_bit)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
flags |= ((dev->pci_conf[reg] & (1 << w_bit)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY);
if (base >= 0x000e0000) {
if (dev->pci_conf[r_reg] & (1 << bit))
if (dev->pci_conf[reg] & (1 << r_bit))
shadowbios |= 1;
if (dev->pci_conf[w_reg] & (1 << bit))
if (dev->pci_conf[reg] & (1 << r_bit))
shadowbios_write |= 1;
}
ali1621_log("%08X-%08X shadow: R%c, W%c\n", base, base + 0x00003fff,
(dev->pci_conf[r_reg] & (1 << bit)) ? 'I' : 'E', (dev->pci_conf[w_reg] & (1 << bit)) ? 'I' : 'E');
(dev->pci_conf[reg] & (1 << r_bit)) ? 'I' : 'E', (dev->pci_conf[reg] & (1 << w_bit)) ? 'I' : 'E');
mem_set_mem_state_both(base, 0x00004000, flags);
}
/* F0000-FFFFF */
base = 0x000f0000;
r_bit = 4;
w_bit = 5;
reg = 0x87;
flags = (dev->pci_conf[reg] & (1 << r_bit)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
flags |= ((dev->pci_conf[reg] & (1 << w_bit)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY);
if (dev->pci_conf[reg] & (1 << r_bit))
shadowbios |= 1;
if (dev->pci_conf[reg] & (1 << r_bit))
shadowbios_write |= 1;
ali1621_log("%08X-%08X shadow: R%c, W%c\n", base, base + 0x0000ffff,
(dev->pci_conf[reg] & (1 << r_bit)) ? 'I' : 'E', (dev->pci_conf[reg] & (1 << w_bit)) ? 'I' : 'E');
mem_set_mem_state_both(base, 0x00010000, flags);
flushmmucache_nopc();
}
@@ -348,7 +422,7 @@ ali1621_write(int func, int addr, uint8_t val, void *priv)
dev->pci_conf[addr] = val;
break;
case 0x6c ... case 0x7b:
case 0x6c ... 0x7b:
/* Bits 22:20 = DRAM Row size:
- 000: 4 MB;
- 001: 8 MB;
@@ -359,6 +433,7 @@ ali1621_write(int func, int addr, uint8_t val, void *priv)
- 110: 256 MB;
- 111: Reserved. */
dev->pci_conf[addr] = val;
spd_write_drbs_ali1621(dev->pci_conf, 0x6c, 0x7b);
break;
case 0x7c ... 0x7f:
@@ -376,148 +451,53 @@ ali1621_write(int func, int addr, uint8_t val, void *priv)
dev->pci_conf[addr] = val & 0xf7;
break;
case 0x54:
dev->pci_conf[addr] = val & 0x3c;
if (mem_size > 0xe00000)
mem_set_mem_state_both(0xe00000, 0x100000, (val & 0x20) ? (MEM_READ_EXTANY | MEM_WRITE_EXTANY) : (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL));
if (mem_size > 0xf00000)
mem_set_mem_state_both(0xf00000, 0x100000, (val & 0x10) ? (MEM_READ_EXTANY | MEM_WRITE_EXTANY) : (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL));
mem_set_mem_state_both(0xa0000, 0x20000, (val & 8) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY));
mem_set_mem_state_both(0x80000, 0x20000, (val & 4) ? (MEM_READ_EXTANY | MEM_WRITE_EXTANY) : (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL));
flushmmucache_nopc();
case 0x83:
dev->pci_conf[addr] = val & 0xfc;
ali1621_smram_recalc(val & 0xfc, dev);
break;
case 0x55: /* SMRAM */
dev->pci_conf[addr] = val & 0x1f;
ali1621_smram_recalc(val, dev);
break;
case 0x56 ... 0x59: /* Shadow RAM */
dev->pci_conf[addr] = val;
case 0x84 ... 0x87:
if (addr == 0x87)
dev->pci_conf[addr] = val & 0x3f;
else
dev->pci_conf[addr] = val;
ali1621_shadow_recalc(val, dev);
break;
case 0x5a: case 0x5b:
case 0x88: case 0x89:
dev->pci_conf[addr] = val;
break;
case 0x5c:
dev->pci_conf[addr] = val;
break;
case 0x5d:
dev->pci_conf[addr] = val & 0x17;
break;
case 0x5e:
dev->pci_conf[addr] = val;
break;
case 0x5f:
dev->pci_conf[addr] = val & 0xc1;
break;
case 0x60 ... 0x6f: /* DRB's */
dev->pci_conf[addr] = val;
spd_write_drbs_interleaved(dev->pci_conf, 0x60, 0x6f, 1);
break;
case 0x70:
dev->pci_conf[addr] = val;
break;
case 0x71:
dev->pci_conf[addr] = val;
break;
case 0x72:
dev->pci_conf[addr] = val & 0xc7;
break;
case 0x73:
dev->pci_conf[addr] = val & 0x1f;
break;
case 0x84: case 0x85:
dev->pci_conf[addr] = val;
break;
case 0x86:
dev->pci_conf[addr] = val & 0x0f;
break;
case 0x87: /* H2PO */
dev->pci_conf[addr] = val;
/* Find where the Shut-down Special cycle is initiated. */
// if (!(val & 0x20))
// outb(0x92, 0x01);
break;
case 0x88:
dev->pci_conf[addr] = val;
break;
case 0x89:
dev->pci_conf[addr] = val;
break;
case 0x8a:
dev->pci_conf[addr] = val;
dev->pci_conf[addr] = val & 0xc5;
break;
case 0x8b:
dev->pci_conf[addr] = val & 0x3f;
dev->pci_conf[addr] = val & 0xbf;
break;
case 0x8c:
dev->pci_conf[addr] = val;
break;
case 0x8d:
dev->pci_conf[addr] = val;
break;
case 0x8e:
dev->pci_conf[addr] = val;
break;
case 0x8f:
case 0x8c ... 0x8f:
dev->pci_conf[addr] = val;
break;
case 0x90:
dev->pci_conf[addr] = val;
pci_bridge_set_ctl(dev->agp_bridge, val);
break;
case 0x91:
dev->pci_conf[addr] = val & 0x07;
break;
case 0x91:
case 0x94 ... 0x97:
dev->pci_conf[addr] = val;
break;
case 0xb4:
if (dev->pci_conf[0x90] & 0x01)
dev->pci_conf[addr] = val & 0x03;
break;
case 0xb5:
if (dev->pci_conf[0x90] & 0x01)
dev->pci_conf[addr] = val & 0x02;
break;
case 0xb7:
if (dev->pci_conf[0x90] & 0x01)
dev->pci_conf[addr] = val;
case 0x98 ... 0x9b:
dev->pci_conf[addr] = val;
break;
case 0xb8:
dev->pci_conf[addr] = val & 0x03;
case 0x9c ... 0x9f:
dev->pci_conf[addr] = val;
break;
case 0xb9:
dev->pci_conf[addr] = val & 0x03;
break;
case 0xbb:
case 0xa0: case 0xa1:
dev->pci_conf[addr] = val;
break;
@@ -533,99 +513,53 @@ ali1621_write(int func, int addr, uint8_t val, void *priv)
break;
case 0xc0:
dev->pci_conf[addr] = val & 0x90;
dev->pci_conf[addr] = val & 0xb1;
break;
case 0xc1: case 0xc2:
case 0xc3:
case 0xc4 ... 0xc7:
dev->pci_conf[addr] = val;
break;
case 0xc8: case 0xc9:
case 0xc8:
dev->pci_conf[addr] = val & 0x8c;
break;
case 0xc9:
dev->pci_conf[addr] = val;
break;
case 0xca:
dev->pci_conf[addr] = val & 0x7f;
break;
case 0xcb:
dev->pci_conf[addr] = val & 0x87;
break;
case 0xcc ... 0xcf:
dev->pci_conf[addr] = val;
break;
case 0xd1:
dev->pci_conf[addr] = val & 0xf1;
case 0xd0:
dev->pci_conf[addr] = val & 0x80;
break;
case 0xd2: case 0xd3:
case 0xd2:
dev->pci_conf[addr] = val & 0x40;
break;
case 0xd3:
dev->pci_conf[addr] = val & 0xb0;
break;
case 0xd4:
dev->pci_conf[addr] = val;
break;
case 0xd5:
dev->pci_conf[addr] = val & 0xef;
break;
case 0xd6: case 0xd7:
dev->pci_conf[addr] = val;
break;
case 0xe0: case 0xe1:
if (dev->pci_conf[0x90] & 0x20)
dev->pci_conf[addr] = val;
break;
case 0xe2:
if (dev->pci_conf[0x90] & 0x20)
dev->pci_conf[addr] = val & 0x3f;
break;
case 0xe3:
if (dev->pci_conf[0x90] & 0x20)
dev->pci_conf[addr] = val & 0xfe;
break;
case 0xe4:
if (dev->pci_conf[0x90] & 0x20)
dev->pci_conf[addr] = val & 0x03;
break;
case 0xe5:
if (dev->pci_conf[0x90] & 0x20)
dev->pci_conf[addr] = val;
break;
case 0xe6:
if (dev->pci_conf[0x90] & 0x20)
dev->pci_conf[addr] = val & 0xc0;
break;
case 0xe7:
if (dev->pci_conf[0x90] & 0x20)
dev->pci_conf[addr] = val;
break;
case 0xe8: case 0xe9:
if (dev->pci_conf[0x90] & 0x04)
dev->pci_conf[addr] = val;
break;
case 0xea:
dev->pci_conf[addr] = val & 0xcf;
break;
case 0xeb:
dev->pci_conf[addr] = val & 0xcf;
break;
case 0xec:
dev->pci_conf[addr] = val & 0x3f;
break;
case 0xed:
case 0xf0 ... 0xff:
dev->pci_conf[addr] = val;
break;
case 0xee:
dev->pci_conf[addr] = val & 0x3e;
break;
case 0xef:
dev->pci_conf[addr] = val;
break;
case 0xf3:
dev->pci_conf[addr] = val & 0x08;
break;
case 0xf5:
dev->pci_conf[addr] = val;
break;
case 0xf6:
dev->pci_conf[addr] = val;
break;
case 0xf7:
dev->pci_conf[addr] = val & 0x43;
break;
}
}
@@ -683,35 +617,26 @@ ali1621_reset(void *priv)
dev->pci_conf[0x7e] = 0xc7;
dev->pci_conf[0x80] = 0x01;
dev->pci_conf[0x81] = 0xc0;
dev->pci_conf[0x89] = 0x20;
dev->pci_conf[0x8a] = 0x20;
dev->pci_conf[0x91] = 0x13;
dev->pci_conf[0x8e] = 0x01;
dev->pci_conf[0xa0] = 0x20;
dev->pci_conf[0xb0] = 0x02;
dev->pci_conf[0xb1] = 0xe0;
dev->pci_conf[0xb2] = 0x10;
dev->pci_conf[0xb4] = 0x03;
dev->pci_conf[0xb5] = 0x02;
dev->pci_conf[0xb7] = 0x1c;
dev->pci_conf[0xc8] = 0xbf;
dev->pci_conf[0xc9] = 0x0a;
dev->pci_conf[0xe0] = 0x01;
dev->pci_conf[0xb7] = 0x20;
dev->pci_conf[0xc0] = 0x80;
dev->pci_conf[0xc9] = 0x28;
dev->pci_conf[0xd4] = 0x10;
dev->pci_conf[0xd5] = 0x01;
dev->pci_conf[0xf0] = dev->pci_conf[0xf4] = dev->pci_conf[0xf8] = dev->pci_conf[0xfc] = 0x20;
dev->pci_conf[0xf1] = dev->pci_conf[0xf5] = dev->pci_conf[0xf9] = dev->pci_conf[0xfd] = 0x43;
dev->pci_conf[0xf2] = dev->pci_conf[0xf6] = dev->pci_conf[0xfa] = dev->pci_conf[0xfe] = 0x21;
dev->pci_conf[0xf3] = dev->pci_conf[0xf7] = dev->pci_conf[0xfb] = dev->pci_conf[0xff] = 0x43;
cpu_cache_int_enabled = 1;
ali1621_write(0, 0x42, 0x00, dev);
ali1621_write(0, 0x54, 0x00, dev);
ali1621_write(0, 0x55, 0x00, dev);
ali1621_write(0, 0x83, 0x08, dev);
for (i = 0; i < 4; i++)
ali1621_write(0, 0x56 + i, 0x00, dev);
ali1621_write(0, 0x60 + i, 0x07, dev);
ali1621_write(0, 0x61 + i, 0x40, dev);
for (i = 0; i < 14; i += 2) {
ali1621_write(0, 0x62 + i, 0x00, dev);
ali1621_write(0, 0x63 + i, 0x00, dev);
}
ali1621_write(0, 0x84 + i, 0x00, dev);
}
@@ -720,7 +645,9 @@ ali1621_close(void *priv)
{
ali1621_t *dev = (ali1621_t *)priv;
smram_del(dev->smram);
smram_del(dev->smram[1]);
smram_del(dev->smram[0]);
free(dev);
}
@@ -733,11 +660,12 @@ ali1621_init(const device_t *info)
pci_add_card(PCI_ADD_NORTHBRIDGE, ali1621_read, ali1621_write, dev);
dev->smram = smram_add();
dev->smram[0] = smram_add();
dev->smram[1] = smram_add();
ali1621_reset(dev);
dev->agp_bridge = device_add(&ali5243_agp_device);
device_add(&ali5247_agp_device);
return dev;
}

476
src/chipset/contaq_82c59x.c Normal file
View File

@@ -0,0 +1,476 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Implementation of the Contaq/Cypress 82C596(A) and 597 chipsets.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2021 Miran Grca.
*/
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include "cpu.h"
#include <86box/timer.h>
#include <86box/io.h>
#include <86box/device.h>
#include <86box/mem.h>
#include <86box/smram.h>
#include <86box/chipset.h>
#ifdef ENABLE_CONTAQ_82C59X_LOG
int contaq_82c59x_do_log = ENABLE_CONTAQ_82C59X_LOG;
static void
contaq_82c59x_log(const char *fmt, ...)
{
va_list ap;
if (contaq_82c59x_do_log)
{
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define contaq_82c59x_log(fmt, ...)
#endif
typedef struct
{
uint32_t phys, virt;
} mem_remapping_t;
typedef struct
{
uint8_t index, green,
smi_status_set,
regs[256], smi_status[2];
smram_t *smram[2];
} contaq_82c59x_t;
static void
contaq_82c59x_isa_speed_recalc(contaq_82c59x_t *dev)
{
if (dev->regs[0x1c] & 0x02)
cpu_set_isa_speed(7159091);
else {
/* TODO: ISA clock dividers for 386 and alt. 486. */
switch (dev->regs[0x10] & 0x03) {
case 0x00:
cpu_set_isa_pci_div(4);
break;
case 0x01:
cpu_set_isa_pci_div(6);
break;
case 0x02:
cpu_set_isa_pci_div(8);
break;
case 0x04:
cpu_set_isa_pci_div(5);
break;
}
}
}
static void
contaq_82c59x_shadow_recalc(contaq_82c59x_t *dev)
{
uint32_t i, base;
uint8_t bit;
shadowbios = shadowbios_write = 0;
/* F0000-FFFFF */
if (dev->regs[0x15] & 0x80) {
shadowbios |= 1;
mem_set_mem_state_both(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_EXTANY);
} else {
shadowbios_write |= 1;
mem_set_mem_state_both(0xf0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
}
/* C0000-CFFFF */
if (dev->regs[0x15] & 0x01)
mem_set_mem_state_both(0xc0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
else {
for (i = 0; i < 4; i++) {
base = 0xc0000 + (i << 14);
bit = 1 << (i + 2);
if (dev->regs[0x15] & bit) {
if (dev->regs[0x15] & 0x02)
mem_set_mem_state_both(base, 0x04000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL);
else
mem_set_mem_state_both(base, 0x04000, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL);
} else
mem_set_mem_state_both(base, 0x04000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
}
}
if (dev->green) {
/* D0000-DFFFF */
if (dev->regs[0x6e] & 0x01)
mem_set_mem_state_both(0xd0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
else {
for (i = 0; i < 4; i++) {
base = 0xd0000 + (i << 14);
bit = 1 << (i + 2);
if (dev->regs[0x6e] & bit) {
if (dev->regs[0x6e] & 0x02)
mem_set_mem_state_both(base, 0x04000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL);
else
mem_set_mem_state_both(base, 0x04000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
} else
mem_set_mem_state_both(base, 0x04000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
}
}
/* E0000-EFFFF */
if (dev->regs[0x6f] & 0x01)
mem_set_mem_state_both(0xe0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
else {
for (i = 0; i < 4; i++) {
base = 0xe0000 + (i << 14);
bit = 1 << (i + 2);
if (dev->regs[0x6f] & bit) {
shadowbios |= 1;
if (dev->regs[0x6f] & 0x02)
mem_set_mem_state_both(base, 0x04000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL);
else {
shadowbios_write |= 1;
mem_set_mem_state_both(base, 0x04000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
}
} else
mem_set_mem_state_both(base, 0x04000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
}
}
}
}
static void
contaq_82c59x_smram_recalc(contaq_82c59x_t *dev)
{
smram_disable(dev->smram[1]);
if (dev->regs[0x70] & 0x04)
smram_enable(dev->smram[1], 0x00040000, 0x000a0000, 0x00020000, 1, 1);
}
static void
contaq_82c59x_write(uint16_t addr, uint8_t val, void *priv)
{
contaq_82c59x_t *dev = (contaq_82c59x_t *)priv;
switch (addr) {
case 0x22:
dev->index = val;
break;
case 0x23:
contaq_82c59x_log("Contaq 82C59x: dev->regs[%02x] = %02x\n", dev->index, val);
if ((dev->index >= 0x60) && !dev->green)
return;
switch (dev->index) {
/* Registers common to 82C596(A) and 82C597. */
case 0x10:
dev->regs[dev->index] = val;
contaq_82c59x_isa_speed_recalc(dev);
break;
case 0x11:
dev->regs[dev->index] = val;
cpu_cache_int_enabled = !!(val & 0x01);
cpu_update_waitstates();
break;
case 0x12:
dev->regs[dev->index] = val;
break;
case 0x13:
dev->regs[dev->index] = val;
break;
case 0x14:
dev->regs[dev->index] = val;
reset_on_hlt = !!(val & 0x80);
break;
case 0x15:
dev->regs[dev->index] = val;
contaq_82c59x_shadow_recalc(dev);
break;
case 0x16:
dev->regs[dev->index] = val;
break;
case 0x17:
dev->regs[dev->index] = val;
break;
case 0x18:
dev->regs[dev->index] = val;
break;
case 0x19:
dev->regs[dev->index] = val;
break;
case 0x1a:
dev->regs[dev->index] = val;
break;
case 0x1b:
dev->regs[dev->index] = val;
break;
case 0x1c:
/* TODO: What's NPRST (generated if bit 3 is set)? */
dev->regs[dev->index] = val;
contaq_82c59x_isa_speed_recalc(dev);
break;
case 0x1d:
dev->regs[dev->index] = val;
break;
case 0x1e:
dev->regs[dev->index] = val;
break;
case 0x1f:
dev->regs[dev->index] = val;
break;
/* Green (82C597-specific) registers. */
case 0x60:
dev->regs[dev->index] = val;
break;
case 0x61:
dev->regs[dev->index] = val;
break;
case 0x62:
dev->regs[dev->index] = val;
break;
case 0x63:
dev->regs[dev->index] = val;
break;
case 0x64:
dev->regs[dev->index] = val;
if (val & 0x80) {
if (dev->regs[0x65] & 0x80)
smi_line = 1;
dev->smi_status[0] |= 0x10;
}
break;
case 0x65:
dev->regs[dev->index] = val;
break;
case 0x66:
dev->regs[dev->index] = val;
break;
case 0x67:
dev->regs[dev->index] = val;
break;
case 0x68:
dev->regs[dev->index] = val;
break;
case 0x69:
dev->regs[dev->index] = val;
break;
case 0x6a:
dev->regs[dev->index] = val;
dev->smi_status_set = !!(val & 0x80);
break;
case 0x6b:
dev->regs[dev->index] = val;
break;
case 0x6c:
dev->regs[dev->index] = val;
break;
case 0x6d:
dev->regs[dev->index] = val;
break;
case 0x6e: case 0x6f:
dev->regs[dev->index] = val;
contaq_82c59x_shadow_recalc(dev);
break;
case 0x70:
dev->regs[dev->index] = val;
contaq_82c59x_smram_recalc(dev);
break;
case 0x71:
dev->regs[dev->index] = val;
break;
case 0x72:
dev->regs[dev->index] = val;
break;
case 0x73:
dev->regs[dev->index] = val;
break;
case 0x74:
dev->regs[dev->index] = val;
break;
case 0x75:
dev->regs[dev->index] = val;
break;
case 0x76:
dev->regs[dev->index] = val;
break;
case 0x77:
dev->regs[dev->index] = val;
break;
case 0x78:
dev->regs[dev->index] = val;
break;
case 0x79:
dev->regs[dev->index] = val;
break;
case 0x7b:
dev->regs[dev->index] = val;
break;
case 0x7c:
dev->regs[dev->index] = val;
break;
}
break;
}
}
static uint8_t
contaq_82c59x_read(uint16_t addr, void *priv)
{
contaq_82c59x_t *dev = (contaq_82c59x_t *)priv;
uint8_t ret = 0xff;
if (addr == 0x23) {
if (dev->index == 0x6a) {
ret = dev->smi_status[dev->smi_status_set];
/* I assume it's cleared on read. */
dev->smi_status[dev->smi_status_set] = 0x00;
} else
ret = dev->regs[dev->index];
}
return ret;
}
static void
contaq_82c59x_close(void *priv)
{
contaq_82c59x_t *dev = (contaq_82c59x_t *)priv;
free(dev);
}
static void *
contaq_82c59x_init(const device_t *info)
{
contaq_82c59x_t *dev = (contaq_82c59x_t *)malloc(sizeof(contaq_82c59x_t));
memset(dev, 0x00, sizeof(contaq_82c59x_t));
dev->green = info->local;
io_sethandler(0x0022, 0x0002, contaq_82c59x_read, NULL, NULL, contaq_82c59x_write, NULL, NULL, dev);
contaq_82c59x_isa_speed_recalc(dev);
cpu_cache_int_enabled = 0;
cpu_update_waitstates();
reset_on_hlt = 0;
contaq_82c59x_shadow_recalc(dev);
if (dev->green) {
/* SMRAM 0: Fixed A0000-BFFFF to A0000-BFFFF DRAM. */
dev->smram[0] = smram_add();
smram_enable(dev->smram[0], 0x000a0000, 0x000a0000, 0x00020000, 0, 1);
/* SMRAM 1: Optional. */
dev->smram[1] = smram_add();
contaq_82c59x_smram_recalc(dev);
}
return dev;
}
const device_t contaq_82c596a_device = {
"Contaq 82C596A",
0,
0,
contaq_82c59x_init,
contaq_82c59x_close,
NULL,
{ NULL },
NULL,
NULL,
NULL
};
const device_t contaq_82c597_device = {
"Contaq 82C597",
0,
1,
contaq_82c59x_init,
contaq_82c59x_close,
NULL,
{ NULL },
NULL,
NULL,
NULL
};