Implemented the Intel 420EX combined northbridge and southbridge, added the ASUS PVI-486AP4, and overhauled SMRAM handling (which also implements some previously missing extended SMRAM features of the 440BX+ and VIA Apollo series of chipsets).

This commit is contained in:
OBattler
2020-06-12 23:29:12 +02:00
parent 2920ad25f3
commit 92a1425896
14 changed files with 1109 additions and 169 deletions

View File

@@ -38,7 +38,6 @@ enum
INTEL_430LX, INTEL_430LX,
INTEL_430NX, INTEL_430NX,
INTEL_430FX, INTEL_430FX,
INTEL_430FX_PB640,
INTEL_430HX, INTEL_430HX,
INTEL_430VX, INTEL_430VX,
INTEL_430TX, INTEL_430TX,
@@ -46,14 +45,15 @@ enum
INTEL_440LX, INTEL_440LX,
INTEL_440EX, INTEL_440EX,
INTEL_440BX, INTEL_440BX,
INTEL_440GX, INTEL_440GX,
INTEL_440ZX INTEL_440ZX
}; };
typedef struct typedef struct
{ {
uint8_t pm2_cntrl, max_func, uint8_t pm2_cntrl, max_func,
smram_locked; smram_locked, max_drb,
drb_default;
uint8_t regs[2][256], regs_locked[2][256]; uint8_t regs[2][256], regs_locked[2][256];
int type; int type;
} i4x0_t; } i4x0_t;
@@ -81,55 +81,28 @@ i4x0_map(uint32_t addr, uint32_t size, int state)
static void static void
i4x0_smram_map(int smm, uint32_t addr, uint32_t size, int ram) i4x0_smram_map(int smm, uint32_t addr, uint32_t size, int is_smram)
{ {
int state = ram ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY); mem_set_mem_state_smram(smm, addr, size, is_smram);
mem_set_mem_state_common(smm, addr, size, state);
flushmmucache();
} }
static void static void
i4x0_smram_handler_phase0(i4x0_t *dev) i4x0_smram_handler_phase0(i4x0_t *dev)
{ {
uint32_t i, n; uint32_t tom = (mem_size << 10);
/* Disable any active mappings. */ /* Disable any active mappings. */
if (dev->type >= INTEL_430FX) { if (smram[0].host_base != 0x00000000) {
if (dev->type >= INTEL_440LX) { i4x0_smram_map(0, smram[0].host_base, ram_smram_mapping[0].size, 0);
/* Disable high extended SMRAM. */ i4x0_smram_map(1, smram[0].host_base, ram_smram_mapping[0].size, 0);
/* TODO: This area should point to A0000-FFFFF. */ }
for (i = 0x100a0000; i < 0x100fffff; i += MEM_GRANULARITY_SIZE) {
/* This is to make sure that if the remaining area is smaller than
or equal to MEM_GRANULARITY_SIZE, we do not change the state of
too much memory. */
n = ((mem_size << 10) - i);
/* Cap to MEM_GRANULARITY_SIZE if i is either at or beyond the end
of RAM or the remaining area is bigger than MEM_GRANULARITY_SIZE. */
if ((i >= (mem_size << 10)) || (n > MEM_GRANULARITY_SIZE))
n = MEM_GRANULARITY_SIZE;
i4x0_smram_map(0, i, n, (i < (mem_size << 10)));
i4x0_smram_map(1, i, n, (i < (mem_size << 10)));
if (n < MEM_GRANULARITY_SIZE) {
i4x0_smram_map(0, i + n, MEM_GRANULARITY_SIZE - n, 0);
i4x0_smram_map(1, i + n, MEM_GRANULARITY_SIZE - n, 0);
}
}
/* Disable TSEG. */ if ((dev->type >= INTEL_440BX) && (smram[1].host_base != 0x00000000)) {
i4x0_smram_map(1, ((mem_size << 10) - (1 << 20)), (1 << 20), 1); i4x0_smram_map(1, smram[1].host_base, ram_smram_mapping[1].size, 0);
}
/* Disable low extended SMRAM. */ tom -= (1 << 20);
i4x0_smram_map(0, 0xa0000, 0x20000, 0); mem_set_mem_state_smm(tom, (1 << 20), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
i4x0_smram_map(1, 0xa0000, 0x20000, 0);
} else {
/* Disable low extended SMRAM. */
i4x0_smram_map(0, 0xa0000, 0x20000, 0);
i4x0_smram_map(0, (mem_size << 10) - 0x10000, 0x10000, 1);
i4x0_smram_map(1, 0xa0000, 0x20000, 0);
i4x0_smram_map(1, (mem_size << 10) - 0x10000, 0x10000, 1);
} }
} }
@@ -138,20 +111,33 @@ static void
i4x0_smram_handler_phase1(i4x0_t *dev) i4x0_smram_handler_phase1(i4x0_t *dev)
{ {
uint8_t *regs = (uint8_t *) dev->regs[0]; uint8_t *regs = (uint8_t *) dev->regs[0];
uint32_t tom = (mem_size << 10);
uint32_t s, base[2] = { 0x000a0000, 0x00020000 }; uint32_t s, base[2] = { 0x000a0000, 0x00020000 };
uint32_t size[2] = { 0, 0 }; uint32_t size[2] = { 0, 0 };
if (dev->type >= INTEL_430FX) { if (dev->type >= INTEL_430FX) {
/* Set temporary bases and sizes. */ /* Set temporary bases and sizes. */
smram[0].ram_base = 0x000a0000;
if ((dev->type >= INTEL_440BX) && (regs[0x73] & 0x80)) { if ((dev->type >= INTEL_440BX) && (regs[0x73] & 0x80)) {
base[0] = 0x100a0000; base[0] = 0x100a0000;
size[0] = 0x00060000; size[0] = 0x00060000;
smram[0].host_base = 0x100a0000;
} else { } else {
base[0] = 0x000a0000; if (((dev->type == INTEL_440LX) || (dev->type == INTEL_440EX)) && ((regs[0x72] & 0x07) == 0x04)) {
size[0] = 0x00020000; base[0] = 0x000c0000;
size[0] = 0x00010000;
smram[0].host_base = smram[0].ram_base = 0x000c0000;
} else {
base[0] = 0x000a0000;
size[0] = 0x00020000;
smram[0].host_base = 0x000a0000;
}
} }
mem_mapping_set_addr(&ram_smram_mapping[0], smram[0].host_base, size[0]);
mem_mapping_set_exec(&ram_smram_mapping[0], ram + smram[0].ram_base);
/* If D_OPEN = 1 and D_LCK = 0, extended SMRAM is visible outside SMM. */ /* If D_OPEN = 1 and D_LCK = 0, extended SMRAM is visible outside SMM. */
i4x0_smram_map(0, base[0], size[0], ((regs[0x72] & 0x70) == 0x40)); i4x0_smram_map(0, base[0], size[0], ((regs[0x72] & 0x70) == 0x40));
@@ -162,10 +148,25 @@ i4x0_smram_handler_phase1(i4x0_t *dev)
if (dev->type >= INTEL_440BX) { if (dev->type >= INTEL_440BX) {
if ((regs[0x72] & 0x08) && (regs[0x73] & 0x01)) { if ((regs[0x72] & 0x08) && (regs[0x73] & 0x01)) {
size[1] = (1 << (17 + ((regs[0x73] >> 1) & 0x03))); size[1] = (1 << (17 + ((regs[0x73] >> 1) & 0x03)));
base[1] = (mem_size << 10) - size[1]; tom -= size[1];
base[1] = tom;
} else } else
base[1] = size[1] = 0x00000000; base[1] = size[1] = 0x00000000;
i4x0_smram_map(1, base[1], size[1], 1);
if (size[1] != 0x00000000) {
mem_set_mem_state_smm(base[1], size[1], MEM_READ_EXTANY | MEM_WRITE_EXTANY);
smram[1].host_base = base[1] + (1 << 28);
smram[1].ram_base = base[1];
mem_mapping_set_addr(&ram_smram_mapping[1], smram[1].host_base, size[1]);
if (smram[1].ram_base < (1 << 30))
mem_mapping_set_exec(&ram_smram_mapping[1], ram + smram[1].ram_base);
else
mem_mapping_set_exec(&ram_smram_mapping[1], ram2 + smram[1].ram_base - (1 << 30));
i4x0_smram_map(1, smram[1].host_base, size[1], 1);
}
} else } else
base[1] = size[1] = 0x00000000; base[1] = size[1] = 0x00000000;
} else { } else {
@@ -204,6 +205,8 @@ i4x0_smram_handler_phase1(i4x0_t *dev)
/* If we are not closed, point to RAM. */ /* If we are not closed, point to RAM. */
} }
} }
flushmmucache();
} }
@@ -259,7 +262,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
default: default:
regs[0x04] = (regs[0x04] & ~0x42) | (val & 0x42); regs[0x04] = (regs[0x04] & ~0x42) | (val & 0x42);
break; break;
case INTEL_430FX: case INTEL_430FX_PB640: case INTEL_430HX: case INTEL_430VX: case INTEL_430TX: case INTEL_430FX: case INTEL_430HX: case INTEL_430VX: case INTEL_430TX:
case INTEL_440FX: case INTEL_440LX: case INTEL_440EX: case INTEL_440FX: case INTEL_440LX: case INTEL_440EX:
regs[0x04] = (regs[0x04] & ~0x02) | (val & 0x02); regs[0x04] = (regs[0x04] & ~0x02) | (val & 0x02);
break; break;
@@ -280,7 +283,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
default: default:
regs[0x07] &= ~(val & 0x70); regs[0x07] &= ~(val & 0x70);
break; break;
case INTEL_430FX: case INTEL_430FX_PB640: case INTEL_430VX: case INTEL_430TX: case INTEL_430FX: case INTEL_430VX: case INTEL_430TX:
case INTEL_440LX: case INTEL_440EX: case INTEL_440LX: case INTEL_440EX:
regs[0x07] &= ~(val & 0x30); regs[0x07] &= ~(val & 0x30);
break; break;
@@ -304,7 +307,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
break; break;
case 0x0f: case 0x0f:
switch (dev->type) { switch (dev->type) {
case INTEL_430FX: case INTEL_430FX_PB640: case INTEL_430HX: case INTEL_430VX: case INTEL_430TX: case INTEL_430FX: case INTEL_430HX: case INTEL_430VX: case INTEL_430TX:
regs[0x0f] = (val & 0x40); regs[0x0f] = (val & 0x40);
break; break;
} }
@@ -365,7 +368,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
case INTEL_430NX: case INTEL_430NX:
regs[0x50] = (val & 0xe7); regs[0x50] = (val & 0xe7);
break; break;
case INTEL_430FX: case INTEL_430FX_PB640: case INTEL_430FX:
regs[0x50] = (val & 0xef); regs[0x50] = (val & 0xef);
break; break;
case INTEL_430HX: case INTEL_430HX:
@@ -420,8 +423,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
case 0x52: /* Cache Control Register */ case 0x52: /* Cache Control Register */
switch (dev->type) { switch (dev->type) {
case INTEL_420TX: case INTEL_420ZX: case INTEL_420TX: case INTEL_420ZX:
case INTEL_430LX: case INTEL_430LX: case INTEL_430FX:
case INTEL_430FX: case INTEL_430FX_PB640:
case INTEL_430VX: case INTEL_430TX: case INTEL_430VX: case INTEL_430TX:
default: default:
regs[0x52] = (val & 0xfb); regs[0x52] = (val & 0xfb);
@@ -516,8 +518,8 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
case INTEL_430NX: case INTEL_440EX: case INTEL_430NX: case INTEL_440EX:
regs[0x57] = val; regs[0x57] = val;
break; break;
case INTEL_430FX: case INTEL_430FX_PB640: case INTEL_430FX: case INTEL_430HX:
case INTEL_430HX: case INTEL_430VX: case INTEL_430VX:
regs[0x57] = val & 0xcf; regs[0x57] = val & 0xcf;
break; break;
case INTEL_430TX: case INTEL_430TX:
@@ -547,8 +549,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
case INTEL_440BX: case INTEL_440ZX: case INTEL_440BX: case INTEL_440ZX:
regs[0x58] = val & 0x03; regs[0x58] = val & 0x03;
break; break;
case INTEL_430FX: case INTEL_430FX_PB640: case INTEL_430FX: case INTEL_440FX:
case INTEL_440FX:
regs[0x58] = val & 0x7f; regs[0x58] = val & 0x7f;
break; break;
case INTEL_430HX: case INTEL_430VX: case INTEL_430HX: case INTEL_430VX:
@@ -629,8 +630,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
default: default:
regs[addr] = val; regs[addr] = val;
break; break;
case INTEL_430FX: case INTEL_430FX_PB640: case INTEL_430FX: case INTEL_430VX:
case INTEL_430VX:
regs[addr] = val & 0x3f; regs[addr] = val & 0x3f;
break; break;
case INTEL_430TX: case INTEL_430TX:
@@ -690,7 +690,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
case INTEL_430VX: case INTEL_430TX: case INTEL_430VX: case INTEL_430TX:
regs[0x68] = val; regs[0x68] = val;
break; break;
case INTEL_430FX: case INTEL_430FX_PB640: case INTEL_430FX:
regs[0x68] = val & 0x1f; regs[0x68] = val & 0x1f;
break; break;
case INTEL_440FX: case INTEL_440LX: case INTEL_440FX: case INTEL_440LX:
@@ -802,7 +802,10 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
if (dev->smram_locked) if (dev->smram_locked)
regs[0x72] = (regs[0x72] & 0xdf) | (val & 0x20); regs[0x72] = (regs[0x72] & 0xdf) | (val & 0x20);
else { else {
regs[0x72] = (regs[0x72] & 0x87) | (val & 0x78); if ((dev->type == INTEL_440LX) || (dev->type == INTEL_440EX))
regs[0x72] = (regs[0x72] & 0x80) | (val & 0x7f);
else
regs[0x72] = (regs[0x72] & 0x87) | (val & 0x78);
dev->smram_locked = (val & 0x10); dev->smram_locked = (val & 0x10);
if (dev->smram_locked) if (dev->smram_locked)
regs[0x72] &= 0xbf; regs[0x72] &= 0xbf;
@@ -814,7 +817,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
regs[0x72] = (regs[0x72] & 0xc0) | (val & 0x3f); regs[0x72] = (regs[0x72] & 0xc0) | (val & 0x3f);
dev->smram_locked = (val & 0x08); dev->smram_locked = (val & 0x08);
if (dev->smram_locked) if (dev->smram_locked)
regs[0x72] &= 0xef; regs[0x72] &= 0xdf;
} }
} }
i4x0_smram_handler_phase1(dev); i4x0_smram_handler_phase1(dev);
@@ -1225,10 +1228,16 @@ i4x0_reset(void *priv)
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
i4x0_write(0, 0x5a + i, 0x00, priv); i4x0_write(0, 0x5a + i, 0x00, priv);
if (dev->type >= INTEL_430FX) for (i = 0; i <= dev->max_drb; i++)
i4x0_write(0, 0x60 + i, dev->drb_default, priv);
if (dev->type >= INTEL_430FX) {
dev->regs[0][0x72] &= 0xef; /* Forcibly unlock the SMRAM register. */
i4x0_write(0, 0x72, 0x02, priv); i4x0_write(0, 0x72, 0x02, priv);
else } else {
dev->regs[0][0x72] &= 0xf7; /* Forcibly unlock the SMRAM register. */
i4x0_write(0, 0x72, 0x00, priv); i4x0_write(0, 0x72, 0x00, priv);
}
if ((dev->type == INTEL_440LX) || (dev->type == INTEL_440BX) || (dev->type == INTEL_440ZX)) { if ((dev->type == INTEL_440LX) || (dev->type == INTEL_440BX) || (dev->type == INTEL_440ZX)) {
for (i = 0; i <= dev->max_func; i++) for (i = 0; i <= dev->max_func; i++)
@@ -1291,6 +1300,8 @@ static void
regs[0x57] = 0x31; regs[0x57] = 0x31;
regs[0x59] = 0x0f; regs[0x59] = 0x0f;
regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = regs[0x65] = 0x02; regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = regs[0x65] = 0x02;
dev->max_drb = 5;
dev->drb_default = 0x02;
break; break;
case INTEL_430LX: case INTEL_430LX:
regs[0x02] = 0xa3; regs[0x03] = 0x04; /* 82434LX/NX */ regs[0x02] = 0xa3; regs[0x03] = 0x04; /* 82434LX/NX */
@@ -1307,6 +1318,8 @@ static void
regs[0x57] = 0x31; regs[0x57] = 0x31;
regs[0x59] = 0x0f; regs[0x59] = 0x0f;
regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = regs[0x65] = 0x02; regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = regs[0x65] = 0x02;
dev->max_drb = 5;
dev->drb_default = 0x02;
break; break;
case INTEL_430NX: case INTEL_430NX:
regs[0x02] = 0xa3; regs[0x03] = 0x04; /* 82434LX/NX */ regs[0x02] = 0xa3; regs[0x03] = 0x04; /* 82434LX/NX */
@@ -1325,12 +1338,12 @@ static void
regs[0x57] = 0x31; regs[0x57] = 0x31;
regs[0x59] = 0x0f; regs[0x59] = 0x0f;
regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = regs[0x65] = regs[0x66] = regs[0x67] = 0x02; regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = regs[0x65] = regs[0x66] = regs[0x67] = 0x02;
dev->max_drb = 7;
dev->drb_default = 0x02;
break; break;
case INTEL_430FX_PB640:
regs[0x08] = 0x02;
/* FALLTHROUGH */
case INTEL_430FX: case INTEL_430FX:
regs[0x02] = 0x2d; regs[0x03] = 0x12; /* SB82437FX-66 */ regs[0x02] = 0x2d; regs[0x03] = 0x12; /* SB82437FX-66 */
regs[0x08] = (info->local >> 8) & 0xff;
regs[0x52] = 0xb2; /* 512 kB PLB cache, set to 0x42 for 256 kB */ regs[0x52] = 0xb2; /* 512 kB PLB cache, set to 0x42 for 256 kB */
if (cpu_busspeed <= 50000000) if (cpu_busspeed <= 50000000)
regs[0x57] |= 0x01; regs[0x57] |= 0x01;
@@ -1340,6 +1353,8 @@ static void
regs[0x57] |= 0x03; regs[0x57] |= 0x03;
regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = 0x02; regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = 0x02;
regs[0x72] = 0x02; regs[0x72] = 0x02;
dev->max_drb = 4;
dev->drb_default = 0x02;
break; break;
case INTEL_430HX: case INTEL_430HX:
regs[0x02] = 0x50; regs[0x03] = 0x12; /* 82439HX */ regs[0x02] = 0x50; regs[0x03] = 0x12; /* 82439HX */
@@ -1352,6 +1367,8 @@ static void
regs[0x57] |= 0x03; regs[0x57] |= 0x03;
regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = regs[0x65] = regs[0x66] = regs[0x67] = 0x02; regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = regs[0x65] = regs[0x66] = regs[0x67] = 0x02;
regs[0x72] = 0x02; regs[0x72] = 0x02;
dev->max_drb = 7;
dev->drb_default = 0x02;
break; break;
case INTEL_430VX: case INTEL_430VX:
regs[0x02] = 0x30; regs[0x03] = 0x70; /* 82437VX */ regs[0x02] = 0x30; regs[0x03] = 0x70; /* 82437VX */
@@ -1371,6 +1388,8 @@ static void
regs[0x72] = 0x02; regs[0x72] = 0x02;
regs[0x74] = 0x0e; regs[0x74] = 0x0e;
regs[0x78] = 0x23; regs[0x78] = 0x23;
dev->max_drb = 4;
dev->drb_default = 0x02;
break; break;
case INTEL_430TX: case INTEL_430TX:
regs[0x02] = 0x00; regs[0x03] = 0x71; /* 82439TX */ regs[0x02] = 0x00; regs[0x03] = 0x71; /* 82439TX */
@@ -1386,6 +1405,8 @@ static void
regs[0x67] |= 0x80; regs[0x67] |= 0x80;
regs[0x70] = 0x20; regs[0x70] = 0x20;
regs[0x72] = 0x02; regs[0x72] = 0x02;
dev->max_drb = 5;
dev->drb_default = 0x02;
break; break;
case INTEL_440FX: case INTEL_440FX:
regs[0x02] = 0x37; regs[0x03] = 0x12; /* 82441FX */ regs[0x02] = 0x37; regs[0x03] = 0x12; /* 82441FX */
@@ -1400,6 +1421,8 @@ static void
regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = regs[0x65] = regs[0x66] = regs[0x67] = 0x02; regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = regs[0x65] = regs[0x66] = regs[0x67] = 0x02;
regs[0x71] = 0x10; regs[0x71] = 0x10;
regs[0x72] = 0x02; regs[0x72] = 0x02;
dev->max_drb = 7;
dev->drb_default = 0x02;
break; break;
case INTEL_440LX: case INTEL_440LX:
dev->max_func = 1; dev->max_func = 1;
@@ -1422,6 +1445,8 @@ static void
regs[0xa4] = 0x03; regs[0xa4] = 0x03;
regs[0xa5] = 0x02; regs[0xa5] = 0x02;
regs[0xa7] = 0x1f; regs[0xa7] = 0x1f;
dev->max_drb = 7;
dev->drb_default = 0x01;
break; break;
case INTEL_440EX: case INTEL_440EX:
dev->max_func = 1; dev->max_func = 1;
@@ -1444,6 +1469,8 @@ static void
regs[0xa4] = 0x03; regs[0xa4] = 0x03;
regs[0xa5] = 0x02; regs[0xa5] = 0x02;
regs[0xa7] = 0x1f; regs[0xa7] = 0x1f;
dev->max_drb = 7;
dev->drb_default = 0x01;
break; break;
case INTEL_440BX: case INTEL_440ZX: case INTEL_440BX: case INTEL_440ZX:
regs[0x7a] = (info->local >> 8) & 0xff; regs[0x7a] = (info->local >> 8) & 0xff;
@@ -1470,6 +1497,8 @@ static void
regs[0xa4] = 0x03; regs[0xa4] = 0x03;
regs[0xa5] = 0x02; regs[0xa5] = 0x02;
regs[0xa7] = 0x1f; regs[0xa7] = 0x1f;
dev->max_drb = 7;
dev->drb_default = 0x01;
break; break;
case INTEL_440GX: case INTEL_440GX:
regs[0x7a] = (info->local >> 8) & 0xff; regs[0x7a] = (info->local >> 8) & 0xff;
@@ -1493,6 +1522,8 @@ static void
regs[0xa4] = 0x03; regs[0xa4] = 0x03;
regs[0xa5] = 0x02; regs[0xa5] = 0x02;
regs[0xa7] = 0x1f; regs[0xa7] = 0x1f;
dev->max_drb = 7;
dev->drb_default = 0x01;
break; break;
} }
@@ -1632,7 +1663,7 @@ const device_t i430fx_pb640_device =
{ {
"Intel SB82437FX-66 (PB640)", "Intel SB82437FX-66 (PB640)",
DEVICE_PCI, DEVICE_PCI,
INTEL_430FX_PB640, 0x0200 | INTEL_430FX,
i4x0_init, i4x0_init,
i4x0_close, i4x0_close,
i4x0_reset, i4x0_reset,

View File

@@ -64,20 +64,12 @@ apollo_map(uint32_t addr, uint32_t size, int state)
static void static void
apollo_smram_map(int smm, uint32_t addr, uint32_t size, int ram) apollo_smram_map(int smm, uint32_t addr, uint32_t size, int is_smram)
{ {
int state = (MEM_READ_EXTANY | MEM_WRITE_EXTANY); mem_mapping_set_addr(&ram_smram_mapping[0], smram[0].host_base, size);
mem_mapping_set_exec(&ram_smram_mapping[0], ram + smram[0].ram_base);
if (ram == 0) mem_set_mem_state_smram_ex(smm, addr, size, is_smram & 0x03);
state = (MEM_READ_EXTANY | MEM_WRITE_EXTANY);
else if (ram == 1)
state = (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
else if (ram == 2)
state = (MEM_READ_EXTERNAL_EX | MEM_WRITE_EXTANY);
else if (ram == 3)
state = (MEM_READ_DISABLED | MEM_WRITE_DISABLED);
mem_set_mem_state_common(smm, addr, size, state);
flushmmucache(); flushmmucache();
} }
@@ -272,6 +264,12 @@ via_apollo_host_bridge_write(int func, int addr, uint8_t val, void *priv)
if ((dev->pci_conf[0][0x63] ^ val) & 0xc0) if ((dev->pci_conf[0][0x63] ^ val) & 0xc0)
apollo_map(0xe0000, 0x10000, (val & 0xc0) >> 6); apollo_map(0xe0000, 0x10000, (val & 0xc0) >> 6);
dev->pci_conf[0][0x63] = val; dev->pci_conf[0][0x63] = val;
mem_set_mem_state_smram_ex(0, 0x00030000, 0x00020000, 0x00);
mem_set_mem_state_smram_ex(1, 0x00030000, 0x00020000, 0x00);
mem_set_mem_state_smram_ex(0, 0x000a0000, 0x00020000, 0x00);
mem_set_mem_state_smram_ex(1, 0x000a0000, 0x00020000, 0x00);
smram[0].host_base = 0x000a0000;
smram[0].ram_base = 0x000a0000;
if (dev->id == 0x0691) switch (val & 0x03) { if (dev->id == 0x0691) switch (val & 0x03) {
case 0x00: case 0x00:
default: default:
@@ -310,9 +308,9 @@ via_apollo_host_bridge_write(int func, int addr, uint8_t val, void *priv)
/* Reserved */ /* Reserved */
apollo_smram_map(1, 0x000a0000, 0x00020000, 3); apollo_smram_map(1, 0x000a0000, 0x00020000, 3);
if (dev->id == 0x0597) { if (dev->id == 0x0597) {
/* TODO: SMI 3xxxx-4xxxx redirect to Axxxx-Bxxxx /* SMI 3xxxx-4xxxx redirect to Axxxx-Bxxxx. */
(this needs a 3xxxx-4xxxx mapping set to EXTERNAL). */ smram[0].host_base = 0x00030000;
apollo_smram_map(1, 0x00030000, 0x00020000, 3); apollo_smram_map(1, 0x00030000, 0x00020000, 1);
} }
apollo_smram_map(0, 0x000a0000, 0x00020000, 3); apollo_smram_map(0, 0x000a0000, 0x00020000, 3);
break; break;

View File

@@ -536,8 +536,8 @@ load_machine(void)
mem_size = (((machines[machine].flags & MACHINE_AT) && (machines[machine].ram_granularity < 128)) ? machines[machine].min_ram*1024 : machines[machine].min_ram); mem_size = (((machines[machine].flags & MACHINE_AT) && (machines[machine].ram_granularity < 128)) ? machines[machine].min_ram*1024 : machines[machine].min_ram);
#endif #endif
if (mem_size > 1048576) if (mem_size > 2097152)
mem_size = 1048576; mem_size = 2097152;
cpu_use_dynarec = !!config_get_int(cat, "cpu_use_dynarec", 0); cpu_use_dynarec = !!config_get_int(cat, "cpu_use_dynarec", 0);

View File

@@ -0,0 +1,15 @@
/*
* 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.
*
* Emulation of Intel 420EX PCI chip.
*
*
*
* Author: Miran Grca, <mgrca8@gmail.com>
* Copyright 2020 Miran Grca.
*/
extern const device_t i420ex_device;

View File

@@ -241,6 +241,7 @@ extern int machine_at_alfredo_init(const machine_t *);
#if defined(DEV_BRANCH) && defined(NO_SIO) #if defined(DEV_BRANCH) && defined(NO_SIO)
extern int machine_at_486sp3g_init(const machine_t *); extern int machine_at_486sp3g_init(const machine_t *);
#endif #endif
extern int machine_at_486ap4_init(const machine_t *);
/* m_at_commodore.c */ /* m_at_commodore.c */
extern int machine_at_cmdpc_init(const machine_t *); extern int machine_at_cmdpc_init(const machine_t *);

View File

@@ -27,31 +27,45 @@
#define MEM_MAPPING_ROM 4 /* Executing from ROM may involve #define MEM_MAPPING_ROM 4 /* Executing from ROM may involve
* additional wait states. */ * additional wait states. */
#define MEM_MAPPING_ROMCS 8 /* respond to ROMCS* */ #define MEM_MAPPING_ROMCS 8 /* respond to ROMCS* */
#define MEM_MAPPING_SMRAM 16 /* on internal bus (RAM) but SMRAM */
#define MEM_MAP_TO_SHADOW_RAM_MASK 1 #define MEM_MAP_TO_SHADOW_RAM_MASK 1
#define MEM_MAP_TO_RAM_ADDR_MASK 2 #define MEM_MAP_TO_RAM_ADDR_MASK 2
#define MEM_READ_ANY 0x00 /* _mem_state layout:
#define MEM_READ_INTERNAL 0x10 Bits 0 - 7: Normal write
#define MEM_READ_EXTERNAL 0x20 Bits 8 -15: Normal read
#define MEM_READ_DISABLED 0x30 Bits 16 -23: SMM write
#define MEM_READ_NORMAL 0x40 /* SMM only - means use the non-SMM state */ Bits 24 -31: SMM read
#define MEM_READ_EXTERNAL_EX 0x50 /* External but with internal exec - needed by the VIA Apollo Pro */ */
#define MEM_READ_ROMCS 0x60 /* EXTERNAL type + ROMC flag */
#define MEM_READ_EXTANY 0x70 /* Any EXTERNAL type */
#define MEM_READ_MASK 0xf0
#define MEM_WRITE_ANY 0x00 #define MEM_READ_ANY 0x0000
#define MEM_WRITE_INTERNAL 0x01 #define MEM_READ_INTERNAL 0x0100
#define MEM_WRITE_EXTERNAL 0x02 #define MEM_READ_EXTERNAL 0x0200
#define MEM_WRITE_DISABLED 0x03 #define MEM_READ_DISABLED 0x0300
#define MEM_WRITE_NORMAL 0x04 /* SMM only - means use the non-SMM state */ #define MEM_READ_NORMAL 0x0400 /* SMM only - means use the non-SMM state */
#define MEM_WRITE_EXTERNAL_EX 0x05 #define MEM_READ_EXTERNAL_EX 0x0500 /* External but with internal exec - needed by the VIA Apollo Pro */
#define MEM_WRITE_ROMCS 0x06 /* EXTERNAL type + ROMC flag */ #define MEM_READ_ROMCS 0x0600 /* EXTERNAL type + ROMC flag */
#define MEM_WRITE_EXTANY 0x07 /* Any EXTERNAL type */ #define MEM_READ_EXTANY 0x0700 /* Any EXTERNAL type */
#define MEM_WRITE_MASK 0x0f #define MEM_READ_SMRAM 0x1000
#define MEM_READ_SMRAM_EX 0x2000
#define MEM_READ_DISABLED_EX 0x4000
#define MEM_READ_MASK 0xff00
#define MEM_STATE_SMM_SHIFT 8 #define MEM_WRITE_ANY 0x0000
#define MEM_WRITE_INTERNAL 0x0001
#define MEM_WRITE_EXTERNAL 0x0002
#define MEM_WRITE_DISABLED 0x0003
#define MEM_WRITE_NORMAL 0x0004 /* SMM only - means use the non-SMM state */
#define MEM_WRITE_EXTERNAL_EX 0x0005
#define MEM_WRITE_ROMCS 0x0006 /* EXTERNAL type + ROMC flag */
#define MEM_WRITE_EXTANY 0x0007 /* Any EXTERNAL type */
#define MEM_WRITE_SMRAM 0x0010
#define MEM_WRITE_SMRAM_EX 0x0020
#define MEM_WRITE_DISABLED_EX 0x0040
#define MEM_WRITE_MASK 0x00ff
#define MEM_STATE_SMM_SHIFT 16
/* #define's for memory granularity, currently 16k, but may /* #define's for memory granularity, currently 16k, but may
change in the future - 4k works, less does not because of change in the future - 4k works, less does not because of
@@ -162,7 +176,14 @@ typedef struct _page_ {
#endif #endif
extern uint8_t *ram; typedef struct
{
uint32_t host_base,
ram_base;
} smram_t;
extern uint8_t *ram, *ram2;
extern uint32_t rammask; extern uint32_t rammask;
extern uint8_t *rom; extern uint8_t *rom;
@@ -185,6 +206,8 @@ extern mem_mapping_t base_mapping,
#endif #endif
ram_remapped_mapping, ram_remapped_mapping,
ram_high_mapping, ram_high_mapping,
ram_2gb_mapping,
ram_smram_mapping[2],
bios_mapping, bios_mapping,
bios_high_mapping; bios_high_mapping;
@@ -193,7 +216,8 @@ extern uint32_t mem_logical_addr;
extern page_t *pages, extern page_t *pages,
**page_lookup; **page_lookup;
extern uint32_t get_phys_virt,get_phys_phys; extern uint32_t get_phys_virt, get_phys_phys;
extern smram_t smram[2];
extern int shadowbios, extern int shadowbios,
shadowbios_write; shadowbios_write;
@@ -278,9 +302,14 @@ extern void mem_mapping_recalc(uint64_t base, uint64_t size);
extern void mem_set_mem_state_common(int smm, uint32_t base, uint32_t size, int state); extern void mem_set_mem_state_common(int smm, uint32_t base, uint32_t size, int state);
extern void mem_set_mem_state_smram(int smm, uint32_t base, uint32_t size, int is_smram);
extern void mem_set_mem_state_smram_ex(int smm, uint32_t base, uint32_t size, int is_smram);
extern void mem_set_mem_state(uint32_t base, uint32_t size, int state); extern void mem_set_mem_state(uint32_t base, uint32_t size, int state);
extern void mem_set_mem_state_smm(uint32_t base, uint32_t size, int state); extern void mem_set_mem_state_smm(uint32_t base, uint32_t size, int state);
extern void mem_set_mem_state_both(uint32_t base, uint32_t size, int state);
extern uint8_t mem_readb_phys(uint32_t addr); extern uint8_t mem_readb_phys(uint32_t addr);
extern uint16_t mem_readw_phys(uint32_t addr); extern uint16_t mem_readw_phys(uint32_t addr);
extern uint32_t mem_readl_phys(uint32_t addr); extern uint32_t mem_readl_phys(uint32_t addr);
@@ -297,6 +326,13 @@ extern void mem_write_ram(uint32_t addr, uint8_t val, void *priv);
extern void mem_write_ramw(uint32_t addr, uint16_t val, void *priv); extern void mem_write_ramw(uint32_t addr, uint16_t val, void *priv);
extern void mem_write_raml(uint32_t addr, uint32_t val, void *priv); extern void mem_write_raml(uint32_t addr, uint32_t val, void *priv);
extern uint8_t mem_read_smram(uint32_t addr, void *priv);
extern uint16_t mem_read_smramw(uint32_t addr, void *priv);
extern uint32_t mem_read_smraml(uint32_t addr, void *priv);
extern void mem_write_smram(uint32_t addr, uint8_t val, void *priv);
extern void mem_write_smramw(uint32_t addr, uint16_t val, void *priv);
extern void mem_write_smraml(uint32_t addr, uint32_t val, void *priv);
extern uint8_t mem_read_bios(uint32_t addr, void *priv); extern uint8_t mem_read_bios(uint32_t addr, void *priv);
extern uint16_t mem_read_biosw(uint32_t addr, void *priv); extern uint16_t mem_read_biosw(uint32_t addr, void *priv);
extern uint32_t mem_read_biosl(uint32_t addr, void *priv); extern uint32_t mem_read_biosl(uint32_t addr, void *priv);

564
src/intel_420ex.c Normal file
View File

@@ -0,0 +1,564 @@
/*
* 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.
*
* Emulation of Intel 82420EX chipset that acts as both the
* northbridge and the southbridge.
*
*
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2020 Miran Grca.
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <86box/86box.h>
#include <86box/device.h>
#include <86box/io.h>
#include <86box/apm.h>
#include <86box/dma.h>
#include <86box/mem.h>
#include <86box/pci.h>
#include <86box/timer.h>
#include <86box/pit.h>
#include <86box/port_92.h>
#include <86box/hdc_ide.h>
#include <86box/hdc.h>
#include <86box/machine.h>
#include <86box/intel_420ex.h>
#define MEM_STATE_SHADOW_R 0x01
#define MEM_STATE_SHADOW_W 0x02
#define MEM_STATE_SMRAM 0x04
typedef struct
{
uint8_t id, smram_locked,
regs[256];
uint16_t timer_base,
timer_latch;
double fast_off_period;
pc_timer_t timer, fast_off_timer;
apm_t * apm;
port_92_t * port_92;
} i420ex_t;
#ifdef ENABLE_I420EX_LOG
int i420ex_do_log = ENABLE_I420EX_LOG;
static void
i420ex_log(const char *fmt, ...)
{
va_list ap;
if (i420ex_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define i420ex_log(fmt, ...)
#endif
static void
i420ex_map(uint32_t addr, uint32_t size, int state)
{
switch (state & 3) {
case 0:
mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
break;
case 1:
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY);
break;
case 2:
mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
break;
case 3:
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
break;
}
flushmmucache_nopc();
}
static void
i420ex_smram_map(i420ex_t *dev, int smm, uint32_t addr, uint32_t size, int is_smram)
{
mem_set_mem_state_smram(smm, addr, size, is_smram);
flushmmucache();
}
static void
i420ex_smram_handler_phase0(i420ex_t *dev)
{
/* Disable low extended SMRAM. */
i420ex_smram_map(dev, 0, 0xa0000, 0x60000, 0);
i420ex_smram_map(dev, 1, 0xa0000, 0x60000, 0);
}
static void
i420ex_smram_handler_phase1(i420ex_t *dev)
{
uint8_t *regs = (uint8_t *) dev->regs;
uint32_t base = 0x000a0000;
uint32_t size = 0x00010000;
switch (regs[0x70] & 0x07) {
case 0: case 1:
default:
base = size = 0x00000000;
break;
case 2:
base = 0x000a0000;
smram[0].host_base = 0x000a0000;
smram[0].ram_base = 0x000a0000;
break;
case 3:
base = 0x000b0000;
smram[0].host_base = 0x000b0000;
smram[0].ram_base = 0x000b0000;
break;
case 4:
base = 0x000c0000;
smram[0].host_base = 0x000c0000;
smram[0].ram_base = 0x000a0000;
break;
case 5:
base = 0x000d0000;
smram[0].host_base = 0x000d0000;
smram[0].ram_base = 0x000a0000;
break;
case 6:
base = 0x000e0000;
smram[0].host_base = 0x000e0000;
smram[0].ram_base = 0x000a0000;
break;
case 7:
base = 0x000f0000;
smram[0].host_base = 0x000f0000;
smram[0].ram_base = 0x000a0000;
break;
}
if (base != 0x00000000) {
mem_mapping_set_addr(&ram_smram_mapping[0], smram[0].host_base, 0x00010000);
mem_mapping_set_exec(&ram_smram_mapping[0], ram + smram[0].ram_base);
/* If OSS = 1 and LSS = 0, extended SMRAM is visible outside SMM. */
i420ex_smram_map(dev, 0, base, size, (regs[0x70] & 0x70) == 0x40);
/* If the register is set accordingly, disable the mapping also in SMM. */
i420ex_smram_map(dev, 1, base, size, !(regs[0x70] & 0x20));
}
}
static void
i420ex_write(int func, int addr, uint8_t val, void *priv)
{
i420ex_t *dev = (i420ex_t *) priv;
if (func > 0)
return;
if (((addr >= 0x0f) && (addr < 0x4c)) && (addr != 0x40))
return;
/* The IB (original) variant of the I420EX has no PCI IRQ steering. */
if ((addr >= 0x60) && (addr <= 0x63) && (dev->id < 0x03))
return;
switch (addr) {
case 0x05:
dev->regs[addr] = (val & 0x01);
break;
case 0x07:
dev->regs[addr] &= ~(val & 0xf0);
break;
case 0x40:
dev->regs[addr] = (val & 0x7f);
break;
case 0x44:
dev->regs[addr] = (val & 0x07);
break;
case 0x48:
dev->regs[addr] = (val & 0x3f);
#ifdef USE_420EX_IDE
ide_pri_disable();
switch (val & 0x03) {
case 0x01:
ide_set_base(0, 0x01f0);
ide_set_side(0, 0x03f6);
ide_pri_enable();
break;
case 0x02:
ide_set_base(0, 0x0170);
ide_set_side(0, 0x0376);
ide_pri_enable();
break;
}
#endif
break;
case 0x49: case 0x53:
dev->regs[addr] = (val & 0x1f);
break;
case 0x4c: case 0x51:
case 0x57:
case 0x60: case 0x61: case 0x62: case 0x63:
case 0x64:
case 0x68: case 0x69:
dev->regs[addr] = val;
if (addr == 0x4c) {
dma_alias_remove();
if (!(val & 0x80))
dma_alias_set();
}
break;
case 0x4d:
dev->regs[addr] = (dev->regs[addr] & 0xef) | (val & 0x10);
break;
case 0x4e:
dev->regs[addr] = (val & 0xf7);
break;
case 0x50:
dev->regs[addr] = (val & 0x0f);
break;
case 0x52:
dev->regs[addr] = (val & 0x7f);
break;
case 0x56:
dev->regs[addr] = (val & 0x3e);
break;
case 0x59: /* PAM0 */
if ((dev->regs[0x59] ^ val) & 0xf0) {
i420ex_map(0xf0000, 0x10000, val >> 4);
shadowbios = (val & 0x10);
}
dev->regs[0x59] = val & 0xf0;
break;
case 0x5a: /* PAM1 */
if ((dev->regs[0x5a] ^ val) & 0x0f)
i420ex_map(0xc0000, 0x04000, val & 0xf);
if ((dev->regs[0x5a] ^ val) & 0xf0)
i420ex_map(0xc4000, 0x04000, val >> 4);
dev->regs[0x5a] = val;
break;
case 0x5b: /*PAM2 */
if ((dev->regs[0x5b] ^ val) & 0x0f)
i420ex_map(0xc8000, 0x04000, val & 0xf);
if ((dev->regs[0x5b] ^ val) & 0xf0)
i420ex_map(0xcc000, 0x04000, val >> 4);
dev->regs[0x5b] = val;
break;
case 0x5c: /*PAM3 */
if ((dev->regs[0x5c] ^ val) & 0x0f)
i420ex_map(0xd0000, 0x04000, val & 0xf);
if ((dev->regs[0x5c] ^ val) & 0xf0)
i420ex_map(0xd4000, 0x04000, val >> 4);
dev->regs[0x5c] = val;
break;
case 0x5d: /* PAM4 */
if ((dev->regs[0x5d] ^ val) & 0x0f)
i420ex_map(0xd8000, 0x04000, val & 0xf);
if ((dev->regs[0x5d] ^ val) & 0xf0)
i420ex_map(0xdc000, 0x04000, val >> 4);
dev->regs[0x5d] = val;
break;
case 0x5e: /* PAM5 */
if ((dev->regs[0x5e] ^ val) & 0x0f)
i420ex_map(0xe0000, 0x04000, val & 0xf);
if ((dev->regs[0x5e] ^ val) & 0xf0)
i420ex_map(0xe4000, 0x04000, val >> 4);
dev->regs[0x5e] = val;
break;
case 0x5f: /* PAM6 */
if ((dev->regs[0x5f] ^ val) & 0x0f)
i420ex_map(0xe8000, 0x04000, val & 0xf);
if ((dev->regs[0x5f] ^ val) & 0xf0)
i420ex_map(0xec000, 0x04000, val >> 4);
dev->regs[0x5f] = val;
break;
case 0x66: case 0x67:
i420ex_log("Set IRQ routing: INT %c -> %02X\n", 0x41 + (addr & 0x01), val);
dev->regs[addr] = val & 0x8f;
if (val & 0x80)
pci_set_irq_routing(PCI_INTA + (addr & 0x01), PCI_IRQ_DISABLED);
else
pci_set_irq_routing(PCI_INTA + (addr & 0x01), val & 0xf);
break;
case 0x70: /* SMRAM */
i420ex_smram_handler_phase0(dev);
if (dev->smram_locked)
dev->regs[0x70] = (dev->regs[0x70] & 0xdf) | (val & 0x20);
else {
dev->regs[0x70] = (dev->regs[0x70] & 0x88) | (val & 0x77);
dev->smram_locked = (val & 0x10);
if (dev->smram_locked)
dev->regs[0x70] &= 0xbf;
}
i420ex_smram_handler_phase1(dev);
break;
case 0xa0:
dev->regs[addr] = val & 0x1f;
apm_set_do_smi(dev->apm, !!(val & 0x01) && !!(dev->regs[0xa2] & 0x80));
switch ((val & 0x18) >> 3) {
case 0x00:
dev->fast_off_period = PCICLK * 32768.0 * 60000.0;
break;
case 0x01:
default:
dev->fast_off_period = 0.0;
break;
case 0x02:
dev->fast_off_period = PCICLK;
break;
case 0x03:
dev->fast_off_period = PCICLK * 32768.0;
break;
}
cpu_fast_off_count = dev->regs[0xa8] + 1;
timer_disable(&dev->fast_off_timer);
if (dev->fast_off_period != 0.0)
timer_on_auto(&dev->fast_off_timer, dev->fast_off_period);
break;
case 0xa2:
dev->regs[addr] = val & 0xff;
apm_set_do_smi(dev->apm, !!(dev->regs[0xa0] & 0x01) && !!(val & 0x80));
break;
case 0xaa: case 0xac: case 0xae:
if (dev->id == 0x03)
dev->regs[addr] = val & 0xff;
break;
case 0xa4:
dev->regs[addr] = val & 0xfb;
cpu_fast_off_flags = (cpu_fast_off_flags & 0xffffff00) | dev->regs[addr];
break;
case 0xa5:
dev->regs[addr] = val;
cpu_fast_off_flags = (cpu_fast_off_flags & 0xffff00ff) | (dev->regs[addr] << 8);
break;
case 0xa7:
dev->regs[addr] = val & 0xe0;
cpu_fast_off_flags = (cpu_fast_off_flags & 0x00ffffff) | (dev->regs[addr] << 24);
break;
case 0xa8:
dev->regs[addr] = val & 0xff;
cpu_fast_off_val = val;
cpu_fast_off_count = val + 1;
timer_disable(&dev->fast_off_timer);
if (dev->fast_off_period != 0.0)
timer_on_auto(&dev->fast_off_timer, dev->fast_off_period);
break;
}
}
static uint8_t
i420ex_read(int func, int addr, void *priv)
{
i420ex_t *dev = (i420ex_t *) priv;
uint8_t ret;
ret = 0xff;
if (func == 0)
ret = dev->regs[addr];
return ret;
}
static void
i420ex_reset_hard(void *priv)
{
i420ex_t *dev = (i420ex_t *) priv;
memset(dev->regs, 0, 256);
dev->regs[0x00] = 0x86; dev->regs[0x01] = 0x80; /*Intel*/
dev->regs[0x02] = 0x86; dev->regs[0x03] = 0x04; /*82378IB (I420EX)*/
dev->regs[0x04] = 0x07;
dev->regs[0x07] = 0x02;
dev->regs[0x08] = dev->id;
dev->regs[0x4c] = 0x4d;
dev->regs[0x4e] = 0x03;
/* Bits 2:1 of register 50h are 00 is 25 MHz, and 01 if 33 MHz, 10 and 11 are reserved. */
if (cpu_busspeed >= 33333333)
dev->regs[0x50] |= 0x02;
dev->regs[0x51] = 0x80;
dev->regs[0x60] = dev->regs[0x61] = dev->regs[0x62] = dev->regs[0x63] = dev->regs[0x64] = 0x01;
dev->regs[0x66] = 0x80; dev->regs[0x67] = 0x80;
dev->regs[0x69] = 0x02;
dev->regs[0xa0] = 0x08;
dev->regs[0xa8] = 0x0f;
mem_set_mem_state(0x000a0000, 0x00060000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
mem_set_mem_state_smm(0x000a0000, 0x00060000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED);
pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED);
pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED);
pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED);
}
static void
i420ex_apm_out(uint16_t port, uint8_t val, void *p)
{
i420ex_t *dev = (i420ex_t *) p;
if (dev->apm->do_smi)
dev->regs[0xaa] |= 0x80;
}
static void
i420ex_fast_off_count(void *priv)
{
i420ex_t *dev = (i420ex_t *) priv;
cpu_fast_off_count--;
if (cpu_fast_off_count == 0) {
smi_line = 1;
dev->regs[0xaa] |= 0x20;
cpu_fast_off_count = dev->regs[0xa8] + 1;
}
timer_on_auto(&dev->fast_off_timer, dev->fast_off_period);
}
static void
i420ex_reset(void *p)
{
i420ex_t *dev = (i420ex_t *) p;
int i;
for (i = 0; i < 7; i++)
i420ex_write(0, 0x59 + i, 0x00, p);
for (i = 0; i <= 4; i++)
i420ex_write(0, 0x60 + i, 0x01, p);
dev->regs[0x70] &= 0xef; /* Forcibly unlock the SMRAM register. */
dev->smram_locked = 0;
i420ex_write(0, 0x70, 0x00, p);
mem_set_mem_state(0x000a0000, 0x00060000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
mem_set_mem_state_smm(0x000a0000, 0x00060000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
i420ex_write(0, 0xa0, 0x08, p);
i420ex_write(0, 0xa2, 0x00, p);
i420ex_write(0, 0xa4, 0x00, p);
i420ex_write(0, 0xa5, 0x00, p);
i420ex_write(0, 0xa6, 0x00, p);
i420ex_write(0, 0xa7, 0x00, p);
i420ex_write(0, 0xa8, 0x0f, p);
}
static void
i420ex_close(void *p)
{
i420ex_t *dev = (i420ex_t *)p;
free(dev);
}
static void
i420ex_speed_changed(void *priv)
{
i420ex_t *dev = (i420ex_t *) priv;
int te;
te = timer_is_enabled(&dev->timer);
timer_disable(&dev->timer);
if (te)
timer_set_delay_u64(&dev->timer, ((uint64_t) dev->timer_latch) * TIMER_USEC);
if (dev->id == 0x03) {
te = timer_is_enabled(&dev->fast_off_timer);
timer_stop(&dev->fast_off_timer);
if (te)
timer_on_auto(&dev->fast_off_timer, dev->fast_off_period);
}
}
static void *
i420ex_init(const device_t *info)
{
i420ex_t *dev = (i420ex_t *) malloc(sizeof(i420ex_t));
memset(dev, 0, sizeof(i420ex_t));
pci_add_card(PCI_ADD_NORTHBRIDGE, i420ex_read, i420ex_write, dev);
dev->id = info->local;
timer_add(&dev->fast_off_timer, i420ex_fast_off_count, dev, 0);
i420ex_reset_hard(dev);
cpu_fast_off_flags = 0x00000000;
cpu_fast_off_val = dev->regs[0xa8];
cpu_fast_off_count = cpu_fast_off_val + 1;
dev->apm = device_add(&apm_pci_device);
/* APM intercept handler to update 82420EX SMI status on APM SMI. */
io_sethandler(0x00b2, 0x0001, NULL, NULL, NULL, i420ex_apm_out, NULL, NULL, dev);
dev->port_92 = device_add(&port_92_pci_device);
dma_alias_set();
#ifdef USE_420EX_IDE
device_add(&ide_pci_device);
ide_pri_disable();
#else
device_add(&ide_pci_2ch_device);
#endif
return dev;
}
const device_t i420ex_device =
{
"Intel 82420EX",
DEVICE_PCI,
0x00,
i420ex_init,
i420ex_close,
i420ex_reset,
NULL,
i420ex_speed_changed,
NULL,
NULL
};

View File

@@ -173,7 +173,7 @@ sio_write(int func, int addr, uint8_t val, void *priv)
return; return;
dma_alias_remove(); dma_alias_remove();
if (val & 0x40) if (!(val & 0x40))
dma_alias_set(); dma_alias_set();
} else } else
dev->regs[addr] = (val & 0x3f); dev->regs[addr] = (val & 0x3f);

View File

@@ -40,6 +40,7 @@
#include <86box/video.h> #include <86box/video.h>
#include <86box/intel_flash.h> #include <86box/intel_flash.h>
#include <86box/sst_flash.h> #include <86box/sst_flash.h>
#include <86box/intel_420ex.h>
#include <86box/intel_sio.h> #include <86box/intel_sio.h>
#include <86box/scsi_ncr53c8xx.h> #include <86box/scsi_ncr53c8xx.h>
#include <86box/machine.h> #include <86box/machine.h>
@@ -474,10 +475,38 @@ machine_at_486sp3g_init(const machine_t *model)
device_add(&sio_device); /* Site says it has a ZB, but the BIOS is designed for an IB. */ device_add(&sio_device); /* Site says it has a ZB, but the BIOS is designed for an IB. */
device_add(&pc87306_device); /*PC87332*/ device_add(&pc87306_device); /*PC87332*/
device_add(&sst_flash_29ee010_device); device_add(&sst_flash_29ee010_device);
device_add(&ncr53c810_pci_device);
device_add(&i420zx_device); device_add(&i420zx_device);
return ret; return ret;
} }
#endif #endif
int
machine_at_486ap4_init(const machine_t *model)
{
int ret;
ret = bios_load_linear(L"roms/machines/486ap4/0205.002",
0x000e0000, 131072, 0);
if (bios_only || !ret)
return ret;
machine_at_common_init(model);
pci_init(PCI_CONFIG_TYPE_1 | PCI_NO_IRQ_STEERING);
/* Excluded: 5, 6, 7, 8 */
pci_register_slot(0x05, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x09, PCI_CARD_NORMAL, 1, 2, 3, 4); /* 09 = Slot 1 */
pci_register_slot(0x0a, PCI_CARD_NORMAL, 2, 3, 4, 1); /* 0a = Slot 2 */
pci_register_slot(0x0b, PCI_CARD_NORMAL, 3, 4, 1, 2); /* 0b = Slot 3 */
pci_register_slot(0x0c, PCI_CARD_NORMAL, 4, 1, 2, 3); /* 0c = Slot 4 */
device_add(&keyboard_ps2_ami_pci_device); /* Uses the AMIKEY KBC */
device_add(&fdc_at_device);
device_add(&i420ex_device);
return ret;
}

View File

@@ -198,6 +198,7 @@ const machine_t machines[] = {
#endif #endif
/* 486 machines which utilize the PCI bus */ /* 486 machines which utilize the PCI bus */
{ "[486 PCI] ASUS PVI-486AP4", "486ap4", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 128, 1, 127, machine_at_486ap4_init, NULL },
#if defined(DEV_BRANCH) && defined(NO_SIO) #if defined(DEV_BRANCH) && defined(NO_SIO)
{ "[486 PCI] ASUS PCI/I-486SP3G", "486sp3g", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1, 128, 1, 127, machine_at_486sp3g_init, NULL }, { "[486 PCI] ASUS PCI/I-486SP3G", "486sp3g", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1, 128, 1, 127, machine_at_486sp3g_init, NULL },
#endif #endif
@@ -313,8 +314,7 @@ const machine_t machines[] = {
/* Slot 2 machines */ /* Slot 2 machines */
/* 440GX */ /* 440GX */
/* Till the Heap limit issue is resolved. This board will use 1GB max instead of 2GB */ { "[Slot 2 GX] Gigabyte GA-6GXU", "6gxu", {{"Intel", cpus_Xeon}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 16, 2048, 16, 511, machine_at_6gxu_init, NULL },
{ "[Slot 2 GX] Gigabyte GA-6GXU", "6gxu", {{"Intel", cpus_Xeon}, {"", NULL},{"", NULL},{"", NULL},{"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 16, 1024, 16, 511, machine_at_6gxu_init, NULL },
/* PGA370 machines */ /* PGA370 machines */
/* 440LX */ /* 440LX */

380
src/mem.c
View File

@@ -64,8 +64,10 @@ mem_mapping_t base_mapping,
#endif #endif
ram_remapped_mapping, /* 640..1024K mapping */ ram_remapped_mapping, /* 640..1024K mapping */
ram_high_mapping, /* 1024K+ mapping */ ram_high_mapping, /* 1024K+ mapping */
ram_2gb_mapping, /* 1024M+ mapping */
ram_remapped_mapping, ram_remapped_mapping,
ram_split_mapping, ram_split_mapping,
ram_smram_mapping[2],
bios_mapping, bios_mapping,
bios_high_mapping; bios_high_mapping;
@@ -73,7 +75,7 @@ page_t *pages, /* RAM page table */
**page_lookup; /* pagetable lookup */ **page_lookup; /* pagetable lookup */
uint32_t pages_sz; /* #pages in table */ uint32_t pages_sz; /* #pages in table */
uint8_t *ram; /* the virtual RAM */ uint8_t *ram, *ram2; /* the virtual RAM */
uint32_t rammask; uint32_t rammask;
uint8_t *rom; /* the virtual ROM */ uint8_t *rom; /* the virtual ROM */
@@ -102,6 +104,8 @@ int cachesize = 256;
uint32_t get_phys_virt, uint32_t get_phys_virt,
get_phys_phys; get_phys_phys;
smram_t smram[2] = { { 0x000a0000, 0x000a0000 }, { 0x000a0000, 0x000a0000 } };
int mem_a20_key = 0, int mem_a20_key = 0,
mem_a20_alt = 0, mem_a20_alt = 0,
mem_a20_state = 0; mem_a20_state = 0;
@@ -122,7 +126,7 @@ int use_phys_exec = 0;
static mem_mapping_t *read_mapping[MEM_MAPPINGS_NO]; static mem_mapping_t *read_mapping[MEM_MAPPINGS_NO];
static mem_mapping_t *write_mapping[MEM_MAPPINGS_NO]; static mem_mapping_t *write_mapping[MEM_MAPPINGS_NO];
static uint8_t *_mem_exec[MEM_MAPPINGS_NO]; static uint8_t *_mem_exec[MEM_MAPPINGS_NO];
static int _mem_state[MEM_MAPPINGS_NO]; static uint32_t _mem_state[MEM_MAPPINGS_NO];
#if FIXME #if FIXME
#if (MEM_GRANULARITY_BITS >= 12) #if (MEM_GRANULARITY_BITS >= 12)
@@ -272,10 +276,17 @@ mem_flush_write_page(uint32_t addr, uint32_t virt)
{ {
page_t *page_target = &pages[addr >> 12]; page_t *page_target = &pages[addr >> 12];
int c; int c;
uint32_t a;
for (c = 0; c < 256; c++) { for (c = 0; c < 256; c++) {
if (writelookup[c] != (int) 0xffffffff) { if (writelookup[c] != (int) 0xffffffff) {
uintptr_t target = (uintptr_t)&ram[(uintptr_t)(addr & ~0xfff) - (virt & ~0xfff)]; a = (uintptr_t)(addr & ~0xfff) - (virt & ~0xfff);
uintptr_t target;
if ((addr & ~0xfff) >= (1 << 30))
target = (uintptr_t)&ram2[a - (1 << 30)];
else
target = (uintptr_t)&ram[a];
if (writelookup2[writelookup[c]] == target || page_lookup[writelookup[c]] == page_target) { if (writelookup2[writelookup[c]] == target || page_lookup[writelookup[c]] == page_target) {
writelookup2[writelookup[c]] = -1; writelookup2[writelookup[c]] = -1;
@@ -562,6 +573,8 @@ mem_addr_translate(uint32_t addr, uint32_t chunk_start, uint32_t len)
void void
addreadlookup(uint32_t virt, uint32_t phys) addreadlookup(uint32_t virt, uint32_t phys)
{ {
uint32_t a;
if (virt == 0xffffffff) return; if (virt == 0xffffffff) return;
if (readlookup2[virt>>12] != (uintptr_t) -1) return; if (readlookup2[virt>>12] != (uintptr_t) -1) return;
@@ -569,7 +582,12 @@ addreadlookup(uint32_t virt, uint32_t phys)
if (readlookup[readlnext] != (int) 0xffffffff) if (readlookup[readlnext] != (int) 0xffffffff)
readlookup2[readlookup[readlnext]] = -1; readlookup2[readlookup[readlnext]] = -1;
readlookup2[virt>>12] = (uintptr_t)&ram[(uintptr_t)(phys & ~0xFFF) - (uintptr_t)(virt & ~0xfff)]; a = (uintptr_t)(phys & ~0xfff) - (uintptr_t)(virt & ~0xfff);
if ((phys & ~0xfff) >= (1 << 30))
readlookup2[virt>>12] = (uintptr_t)&ram2[a - (1 << 30)];
else
readlookup2[virt>>12] = (uintptr_t)&ram[a];
readlookupp[readlnext] = mmu_perm; readlookupp[readlnext] = mmu_perm;
readlookup[readlnext++] = virt >> 12; readlookup[readlnext++] = virt >> 12;
@@ -582,6 +600,8 @@ addreadlookup(uint32_t virt, uint32_t phys)
void void
addwritelookup(uint32_t virt, uint32_t phys) addwritelookup(uint32_t virt, uint32_t phys)
{ {
uint32_t a;
if (virt == 0xffffffff) return; if (virt == 0xffffffff) return;
if (page_lookup[virt >> 12]) return; if (page_lookup[virt >> 12]) return;
@@ -601,8 +621,14 @@ addwritelookup(uint32_t virt, uint32_t phys)
#endif #endif
#endif #endif
page_lookup[virt >> 12] = &pages[phys >> 12]; page_lookup[virt >> 12] = &pages[phys >> 12];
else else {
writelookup2[virt>>12] = (uintptr_t)&ram[(uintptr_t)(phys & ~0xFFF) - (uintptr_t)(virt & ~0xfff)]; a = (uintptr_t)(phys & ~0xfff) - (uintptr_t)(virt & ~0xfff);
if ((phys & ~0xfff) >= (1 << 30))
writelookup2[virt>>12] = (uintptr_t)&ram2[a - (1 << 30)];
else
writelookup2[virt>>12] = (uintptr_t)&ram[a];
}
writelookupp[writelnext] = mmu_perm; writelookupp[writelnext] = mmu_perm;
writelookup[writelnext++] = virt >> 12; writelookup[writelnext++] = virt >> 12;
@@ -1566,6 +1592,87 @@ mem_read_raml(uint32_t addr, void *priv)
} }
uint8_t
mem_read_ram_2gb(uint32_t addr, void *priv)
{
#ifdef ENABLE_MEM_LOG
if ((addr >= 0xa0000) && (addr <= 0xbffff))
mem_log("Read B %02X from %08X\n", ram[addr], addr);
#endif
addreadlookup(mem_logical_addr, addr);
return ram2[addr - (1 << 30)];
}
uint16_t
mem_read_ram_2gbw(uint32_t addr, void *priv)
{
#ifdef ENABLE_MEM_LOG
if ((addr >= 0xa0000) && (addr <= 0xbffff))
mem_log("Read W %04X from %08X\n", *(uint16_t *)&ram[addr], addr);
#endif
addreadlookup(mem_logical_addr, addr);
return *(uint16_t *)&ram2[addr - (1 << 30)];
}
uint32_t
mem_read_ram_2gbl(uint32_t addr, void *priv)
{
#ifdef ENABLE_MEM_LOG
if ((addr >= 0xa0000) && (addr <= 0xbffff))
mem_log("Read L %08X from %08X\n", *(uint32_t *)&ram[addr], addr);
#endif
addreadlookup(mem_logical_addr, addr);
return *(uint32_t *)&ram2[addr - (1 << 30)];
}
uint8_t
mem_read_smram(uint32_t addr, void *priv)
{
smram_t *dev = (smram_t *) priv;
uint32_t new_addr = addr - dev->host_base + dev->ram_base;
if (new_addr >= (1 << 30))
return mem_read_ram_2gb(new_addr, priv);
else
return mem_read_ram(new_addr, priv);
}
uint16_t
mem_read_smramw(uint32_t addr, void *priv)
{
smram_t *dev = (smram_t *) priv;
uint32_t new_addr = addr - dev->host_base + dev->ram_base;
if (new_addr >= (1 << 30))
return mem_read_ram_2gbw(new_addr, priv);
else
return mem_read_ramw(new_addr, priv);
}
uint32_t
mem_read_smraml(uint32_t addr, void *priv)
{
smram_t *dev = (smram_t *) priv;
uint32_t new_addr = addr - dev->host_base + dev->ram_base;
if (new_addr >= (1 << 30))
return mem_read_ram_2gbl(new_addr, priv);
else
return mem_read_raml(new_addr, priv);
}
#ifdef USE_NEW_DYNAREC #ifdef USE_NEW_DYNAREC
static inline int static inline int
page_index(page_t *p) page_index(page_t *p)
@@ -1760,6 +1867,36 @@ mem_write_raml(uint32_t addr, uint32_t val, void *priv)
} }
void
mem_write_smram(uint32_t addr, uint8_t val, void *priv)
{
smram_t *dev = (smram_t *) priv;
uint32_t new_addr = addr - dev->host_base + dev->ram_base;
mem_write_ram(new_addr, val, priv);
}
void
mem_write_smramw(uint32_t addr, uint16_t val, void *priv)
{
smram_t *dev = (smram_t *) priv;
uint32_t new_addr = addr - dev->host_base + dev->ram_base;
mem_write_ramw(new_addr, val, priv);
}
void
mem_write_smraml(uint32_t addr, uint32_t val, void *priv)
{
smram_t *dev = (smram_t *) priv;
uint32_t new_addr = addr - dev->host_base + dev->ram_base;
mem_write_raml(new_addr, val, priv);
}
static uint8_t static uint8_t
mem_read_remapped(uint32_t addr, void *priv) mem_read_remapped(uint32_t addr, void *priv)
{ {
@@ -1924,40 +2061,49 @@ mem_invalidate_range(uint32_t start_addr, uint32_t end_addr)
static __inline int static __inline int
mem_mapping_read_allowed(uint32_t flags, int state, int exec) mem_mapping_read_allowed(uint32_t flags, uint32_t state, int exec)
{ {
int smm_state = state >> MEM_STATE_SMM_SHIFT; uint32_t smm_state = state >> MEM_STATE_SMM_SHIFT;
uint32_t state_masked;
if (in_smm && ((smm_state & MEM_READ_MASK) != MEM_READ_NORMAL)) if (in_smm && ((smm_state & MEM_READ_MASK) != MEM_READ_NORMAL))
state = smm_state; state = smm_state;
switch (state & MEM_READ_MASK) { state_masked = (state & MEM_READ_MASK);
if (state_masked & MEM_READ_SMRAM)
return (flags & MEM_MAPPING_SMRAM);
else if ((state_masked & MEM_READ_SMRAM_EX) && exec)
return (flags & MEM_MAPPING_SMRAM);
else if (state_masked & MEM_READ_DISABLED_EX)
return 0;
else switch (state_masked) {
case MEM_READ_DISABLED: case MEM_READ_DISABLED:
return 0; return 0;
case MEM_READ_ANY: case MEM_READ_ANY:
return 1; return !(flags & MEM_MAPPING_SMRAM);
/* On external and 0 mappings without ROMCS. */ /* On external and 0 mappings without ROMCS. */
case MEM_READ_EXTERNAL: case MEM_READ_EXTERNAL:
return !(flags & MEM_MAPPING_INTERNAL) && !(flags & MEM_MAPPING_ROMCS); return !(flags & MEM_MAPPING_INTERNAL) && !(flags & MEM_MAPPING_ROMCS) && !(flags & MEM_MAPPING_SMRAM);
/* On external and 0 mappings with ROMCS. */ /* On external and 0 mappings with ROMCS. */
case MEM_READ_ROMCS: case MEM_READ_ROMCS:
return !(flags & MEM_MAPPING_INTERNAL) && (flags & MEM_MAPPING_ROMCS); return !(flags & MEM_MAPPING_INTERNAL) && (flags & MEM_MAPPING_ROMCS) && !(flags & MEM_MAPPING_SMRAM);
/* On any external mappings. */ /* On any external mappings. */
case MEM_READ_EXTANY: case MEM_READ_EXTANY:
return !(flags & MEM_MAPPING_INTERNAL); return !(flags & MEM_MAPPING_INTERNAL) && !(flags & MEM_MAPPING_SMRAM);
case MEM_READ_EXTERNAL_EX: case MEM_READ_EXTERNAL_EX:
if (exec) if (exec)
return !(flags & MEM_MAPPING_EXTERNAL); return !(flags & MEM_MAPPING_EXTERNAL) && !(flags & MEM_MAPPING_SMRAM);
else else
return !(flags & MEM_MAPPING_INTERNAL); return !(flags & MEM_MAPPING_INTERNAL) && !(flags & MEM_MAPPING_SMRAM);
case MEM_READ_INTERNAL: case MEM_READ_INTERNAL:
return !(flags & MEM_MAPPING_EXTERNAL); return !(flags & MEM_MAPPING_EXTERNAL) && !(flags & MEM_MAPPING_SMRAM);
default: default:
fatal("mem_mapping_read_allowed : bad state %x\n", state); fatal("mem_mapping_read_allowed : bad state %x\n", state);
@@ -1968,34 +2114,41 @@ mem_mapping_read_allowed(uint32_t flags, int state, int exec)
static __inline int static __inline int
mem_mapping_write_allowed(uint32_t flags, int state) mem_mapping_write_allowed(uint32_t flags, uint32_t state)
{ {
int smm_state = state >> MEM_STATE_SMM_SHIFT; uint32_t smm_state = state >> MEM_STATE_SMM_SHIFT;
uint32_t state_masked;
if (in_smm && ((smm_state & MEM_WRITE_MASK) != MEM_WRITE_NORMAL)) if (in_smm && ((smm_state & MEM_WRITE_MASK) != MEM_WRITE_NORMAL))
state = smm_state; state = smm_state;
switch (state & MEM_WRITE_MASK) { state_masked = (state & MEM_WRITE_MASK);
if (state_masked & MEM_WRITE_SMRAM)
return (flags & MEM_MAPPING_SMRAM);
else if (state_masked & MEM_WRITE_DISABLED_EX)
return 0;
else switch (state_masked) {
case MEM_WRITE_DISABLED: case MEM_WRITE_DISABLED:
return 0; return 0;
case MEM_WRITE_ANY: case MEM_WRITE_ANY:
return 1; return !(flags & MEM_MAPPING_SMRAM);
/* On external and 0 mappings without ROMCS. */ /* On external and 0 mappings without ROMCS. */
case MEM_WRITE_EXTERNAL: case MEM_WRITE_EXTERNAL:
return !(flags & MEM_MAPPING_INTERNAL) && !(flags & MEM_MAPPING_ROMCS); return !(flags & MEM_MAPPING_INTERNAL) && !(flags & MEM_MAPPING_ROMCS) && !(flags & MEM_MAPPING_SMRAM);
/* On external and 0 mappings with ROMCS. */ /* On external and 0 mappings with ROMCS. */
case MEM_WRITE_ROMCS: case MEM_WRITE_ROMCS:
return !(flags & MEM_MAPPING_INTERNAL) && (flags & MEM_MAPPING_ROMCS); return !(flags & MEM_MAPPING_INTERNAL) && (flags & MEM_MAPPING_ROMCS) && !(flags & MEM_MAPPING_SMRAM);
/* On any external mappings. */ /* On any external mappings. */
case MEM_WRITE_EXTANY: case MEM_WRITE_EXTANY:
return !(flags & MEM_MAPPING_INTERNAL); return !(flags & MEM_MAPPING_INTERNAL) && !(flags & MEM_MAPPING_SMRAM);
case MEM_WRITE_INTERNAL: case MEM_WRITE_INTERNAL:
return !(flags & MEM_MAPPING_EXTERNAL); return !(flags & MEM_MAPPING_EXTERNAL) && !(flags & MEM_MAPPING_SMRAM);
default: default:
fatal("mem_mapping_write_allowed : bad state %x\n", state); fatal("mem_mapping_write_allowed : bad state %x\n", state);
@@ -2216,9 +2369,9 @@ mem_set_mem_state_common(int smm, uint32_t base, uint32_t size, int state)
for (c = 0; c < size; c += MEM_GRANULARITY_SIZE) { for (c = 0; c < size; c += MEM_GRANULARITY_SIZE) {
if (smm) if (smm)
_mem_state[(c + base) >> MEM_GRANULARITY_BITS] = (_mem_state[(c + base) >> MEM_GRANULARITY_BITS] & 0x00ff) | ((state & 0xff) << 8); _mem_state[(c + base) >> MEM_GRANULARITY_BITS] = (_mem_state[(c + base) >> MEM_GRANULARITY_BITS] & 0xf0f0ffff) | ((state & 0x0f0f) << MEM_STATE_SMM_SHIFT);
else else
_mem_state[(c + base) >> MEM_GRANULARITY_BITS] = (_mem_state[(c + base) >> MEM_GRANULARITY_BITS] & 0xff00) | (state & 0xff); _mem_state[(c + base) >> MEM_GRANULARITY_BITS] = (_mem_state[(c + base) >> MEM_GRANULARITY_BITS] & 0xfffff0f0) | (state & 0x0f0f);
#ifdef ENABLE_MEM_LOG #ifdef ENABLE_MEM_LOG
if (((c + base) >= 0xa0000) && ((c + base) <= 0xbffff)) if (((c + base) >= 0xa0000) && ((c + base) <= 0xbffff))
mem_log("Set mem state for block at %08X to %02X\n", c + base, state); mem_log("Set mem state for block at %08X to %02X\n", c + base, state);
@@ -2229,6 +2382,63 @@ mem_set_mem_state_common(int smm, uint32_t base, uint32_t size, int state)
} }
void
mem_set_mem_state_smram(int smm, uint32_t base, uint32_t size, int is_smram)
{
uint32_t c, smstate = 0x0000;
smstate = is_smram ? (MEM_READ_SMRAM | MEM_WRITE_SMRAM) : 0x0000;
for (c = 0; c < size; c += MEM_GRANULARITY_SIZE) {
if (smm)
_mem_state[(c + base) >> MEM_GRANULARITY_BITS] = (_mem_state[(c + base) >> MEM_GRANULARITY_BITS] & 0x0f0fffff) | (smstate << MEM_STATE_SMM_SHIFT);
else
_mem_state[(c + base) >> MEM_GRANULARITY_BITS] = (_mem_state[(c + base) >> MEM_GRANULARITY_BITS] & 0xffff0f0f) | smstate;
#ifdef ENABLE_MEM_LOG
if (((c + base) >= 0xa0000) && ((c + base) <= 0xbffff))
mem_log("Set mem state SMRAM flag for block at %08X to %02X\n", c + base, state);
#endif
}
mem_mapping_recalc(base, size);
}
void
mem_set_mem_state_smram_ex(int smm, uint32_t base, uint32_t size, int is_smram)
{
uint32_t c, smstate = 0x0000;
switch (is_smram & 0x03) {
case 0x00:
smstate = 0x0000;
break;
case 0x01:
smstate = (MEM_READ_SMRAM | MEM_WRITE_SMRAM);
break;
case 0x02:
smstate = MEM_READ_SMRAM_EX;
break;
case 0x03:
smstate = (MEM_READ_DISABLED_EX | MEM_WRITE_DISABLED_EX);
break;
}
for (c = 0; c < size; c += MEM_GRANULARITY_SIZE) {
if (smm)
_mem_state[(c + base) >> MEM_GRANULARITY_BITS] = (_mem_state[(c + base) >> MEM_GRANULARITY_BITS] & 0x0f0fffff) | (smstate << MEM_STATE_SMM_SHIFT);
else
_mem_state[(c + base) >> MEM_GRANULARITY_BITS] = (_mem_state[(c + base) >> MEM_GRANULARITY_BITS] & 0xffff0f0f) | smstate;
#ifdef ENABLE_MEM_LOG
if (((c + base) >= 0xa0000) && ((c + base) <= 0xbffff))
mem_log("Set mem state SMRAM flag for block at %08X to %02X\n", c + base, state);
#endif
}
mem_mapping_recalc(base, size);
}
void void
mem_set_mem_state(uint32_t base, uint32_t size, int state) mem_set_mem_state(uint32_t base, uint32_t size, int state)
{ {
@@ -2243,6 +2453,14 @@ mem_set_mem_state_smm(uint32_t base, uint32_t size, int state)
} }
void
mem_set_mem_state_both(uint32_t base, uint32_t size, int state)
{
mem_set_mem_state_common(0, base, size, state);
mem_set_mem_state_common(1, base, size, state);
}
void void
mem_add_bios(void) mem_add_bios(void)
{ {
@@ -2260,16 +2478,16 @@ mem_add_bios(void)
mem_write_null,mem_write_nullw,mem_write_nulll, mem_write_null,mem_write_nullw,mem_write_nulll,
&rom[0x20000], MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM|MEM_MAPPING_ROMCS, 0); &rom[0x20000], MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM|MEM_MAPPING_ROMCS, 0);
mem_set_mem_state(0x0e0000, 0x20000, mem_set_mem_state_both(0x0e0000, 0x20000,
MEM_READ_ROMCS | MEM_WRITE_ROMCS); MEM_READ_ROMCS | MEM_WRITE_ROMCS);
} else { } else {
mem_mapping_add(&bios_mapping, biosaddr, biosmask + 1, mem_mapping_add(&bios_mapping, biosaddr, biosmask + 1,
mem_read_bios,mem_read_biosw,mem_read_biosl, mem_read_bios,mem_read_biosw,mem_read_biosl,
mem_write_null,mem_write_nullw,mem_write_nulll, mem_write_null,mem_write_nullw,mem_write_nulll,
rom, MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM|MEM_MAPPING_ROMCS, 0); rom, MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM|MEM_MAPPING_ROMCS, 0);
mem_set_mem_state(biosaddr, biosmask + 1, mem_set_mem_state_both(biosaddr, biosmask + 1,
MEM_READ_ROMCS | MEM_WRITE_ROMCS); MEM_READ_ROMCS | MEM_WRITE_ROMCS);
} }
if (AT) { if (AT) {
@@ -2278,8 +2496,8 @@ mem_add_bios(void)
mem_write_null,mem_write_nullw,mem_write_nulll, mem_write_null,mem_write_nullw,mem_write_nulll,
rom, MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM|MEM_MAPPING_ROMCS, 0); rom, MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM|MEM_MAPPING_ROMCS, 0);
mem_set_mem_state(biosaddr | (temp_cpu_16bitbus ? 0x00f00000 : 0xfff00000), biosmask + 1, mem_set_mem_state_both(biosaddr | (temp_cpu_16bitbus ? 0x00f00000 : 0xfff00000), biosmask + 1,
MEM_READ_ROMCS | MEM_WRITE_ROMCS); MEM_READ_ROMCS | MEM_WRITE_ROMCS);
} }
} }
@@ -2310,8 +2528,22 @@ mem_reset(void)
free(ram); free(ram);
ram = NULL; ram = NULL;
} }
ram = (uint8_t *)malloc(m); /* allocate and clear the RAM block */ if (ram2 != NULL) {
memset(ram, 0x00, m); free(ram2);
ram2 = NULL;
}
if (mem_size > 2097152)
fatal("Attempting to use more than 2 GB of guest RAM\n");
if (mem_size > 1048576) {
ram = (uint8_t *)malloc(1 << 30); /* allocate and clear the RAM block of the first 1 GB */
memset(ram, 0x00, 1 << 30);
ram2 = (uint8_t *)malloc(m - (1 << 30)); /* allocate and clear the RAM block above 1 GB */
memset(ram2, 0x00, m - (1 << 30));
} else {
ram = (uint8_t *)malloc(m); /* allocate and clear the RAM block */
memset(ram, 0x00, m);
}
/* /*
* Allocate the page table based on how much RAM we have. * Allocate the page table based on how much RAM we have.
@@ -2396,7 +2628,13 @@ mem_log("MEM: reset: new pages=%08lx, pages_sz=%i\n", pages, pages_sz);
#endif #endif
for (c = 0; c < pages_sz; c++) { for (c = 0; c < pages_sz; c++) {
pages[c].mem = &ram[c << 12]; if (mem_size > 1048576) {
if ((c << 12) < (1 << 30))
pages[c].mem = &ram[c << 12];
else
pages[c].mem = &ram2[(c << 12) - (1 << 30)];
} else
pages[c].mem = &ram[c << 12];
if (c < m) { if (c < m) {
pages[c].write_b = mem_write_ramb_page; pages[c].write_b = mem_write_ramb_page;
pages[c].write_w = mem_write_ramw_page; pages[c].write_w = mem_write_ramw_page;
@@ -2420,16 +2658,11 @@ mem_log("MEM: reset: new pages=%08lx, pages_sz=%i\n", pages, pages_sz);
memset(&base_mapping, 0x00, sizeof(base_mapping)); memset(&base_mapping, 0x00, sizeof(base_mapping));
memset(_mem_state, 0x00, sizeof(_mem_state)); memset(_mem_state, 0x00, sizeof(_mem_state));
/* Set SMM states to (MEM_READ_NORMAL | MEM_WRITE_NORMAL). */
for (c = 0; c < MEM_MAPPINGS_NO; c++)
_mem_state[c] |= 0x4400;
mem_set_mem_state(0x000000, (mem_size > 640) ? 0xa0000 : mem_size * 1024, mem_set_mem_state_both(0x000000, (mem_size > 640) ? 0xa0000 : mem_size * 1024,
MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
/* mem_set_mem_state(0x0c0000, 0x40000, mem_set_mem_state_both(0x0a0000, 0x60000,
MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); */ MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
mem_set_mem_state(0x0a0000, 0x60000,
MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
mem_mapping_add(&ram_low_mapping, 0x00000, mem_mapping_add(&ram_low_mapping, 0x00000,
(mem_size > 640) ? 0xa0000 : mem_size * 1024, (mem_size > 640) ? 0xa0000 : mem_size * 1024,
@@ -2439,21 +2672,38 @@ mem_log("MEM: reset: new pages=%08lx, pages_sz=%i\n", pages, pages_sz);
if (mem_size > 1024) { if (mem_size > 1024) {
if (cpu_16bitbus && mem_size > 16256) { if (cpu_16bitbus && mem_size > 16256) {
mem_set_mem_state(0x100000, (16256 - 1024) * 1024, mem_set_mem_state_both(0x100000, (16256 - 1024) * 1024,
MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
mem_mapping_add(&ram_high_mapping, 0x100000, mem_mapping_add(&ram_high_mapping, 0x100000,
((16256 - 1024) * 1024), ((16256 - 1024) * 1024),
mem_read_ram,mem_read_ramw,mem_read_raml, mem_read_ram,mem_read_ramw,mem_read_raml,
mem_write_ram,mem_write_ramw,mem_write_raml, mem_write_ram,mem_write_ramw,mem_write_raml,
ram + 0x100000, MEM_MAPPING_INTERNAL, NULL); ram + 0x100000, MEM_MAPPING_INTERNAL, NULL);
} else { } else {
mem_set_mem_state(0x100000, (mem_size - 1024) * 1024, if (mem_size > 1048576) {
MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); mem_set_mem_state_both(0x100000, (1048576 - 1024) * 1024,
mem_mapping_add(&ram_high_mapping, 0x100000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
((mem_size - 1024) * 1024), mem_mapping_add(&ram_high_mapping, 0x100000,
mem_read_ram,mem_read_ramw,mem_read_raml, ((1048576 - 1024) * 1024),
mem_write_ram,mem_write_ramw,mem_write_raml, mem_read_ram,mem_read_ramw,mem_read_raml,
ram + 0x100000, MEM_MAPPING_INTERNAL, NULL); mem_write_ram,mem_write_ramw,mem_write_raml,
ram + 0x100000, MEM_MAPPING_INTERNAL, NULL);
mem_set_mem_state_both((1 << 30), (mem_size - 1048576) * 1024,
MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
mem_mapping_add(&ram_2gb_mapping, (1 << 30),
((mem_size - 1048576) * 1024),
mem_read_ram_2gb,mem_read_ram_2gbw,mem_read_ram_2gbl,
mem_write_ram,mem_write_ramw,mem_write_raml,
ram2, MEM_MAPPING_INTERNAL, NULL);
} else {
mem_set_mem_state_both(0x100000, (mem_size - 1024) * 1024,
MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
mem_mapping_add(&ram_high_mapping, 0x100000,
((mem_size - 1024) * 1024),
mem_read_ram,mem_read_ramw,mem_read_raml,
mem_write_ram,mem_write_ramw,mem_write_raml,
ram + 0x100000, MEM_MAPPING_INTERNAL, NULL);
}
} }
} }
@@ -2462,11 +2712,23 @@ mem_log("MEM: reset: new pages=%08lx, pages_sz=%i\n", pages, pages_sz);
mem_read_ram,mem_read_ramw,mem_read_raml, mem_read_ram,mem_read_ramw,mem_read_raml,
mem_write_ram,mem_write_ramw,mem_write_raml, mem_write_ram,mem_write_ramw,mem_write_raml,
ram + 0xc0000, MEM_MAPPING_INTERNAL, NULL); */ ram + 0xc0000, MEM_MAPPING_INTERNAL, NULL); */
if (mem_size > 768) if (mem_size > 768) {
mem_mapping_add(&ram_mid_mapping, 0xa0000, 0x60000, mem_mapping_add(&ram_mid_mapping, 0xa0000, 0x60000,
mem_read_ram,mem_read_ramw,mem_read_raml, mem_read_ram,mem_read_ramw,mem_read_raml,
mem_write_ram,mem_write_ramw,mem_write_raml, mem_write_ram,mem_write_ramw,mem_write_raml,
ram + 0xa0000, MEM_MAPPING_INTERNAL, NULL); ram + 0xa0000, MEM_MAPPING_INTERNAL, NULL);
}
mem_mapping_add(&ram_smram_mapping[0], 0xa0000, 0x60000,
mem_read_smram,mem_read_smramw,mem_read_smraml,
mem_write_smram,mem_write_smramw,mem_write_smraml,
ram + 0xa0000, MEM_MAPPING_SMRAM, &(smram[0]));
mem_mapping_add(&ram_smram_mapping[1], 0xa0000, 0x60000,
mem_read_ram,mem_read_ramw,mem_read_raml,
mem_write_ram,mem_write_ramw,mem_write_raml,
ram + 0xa0000, MEM_MAPPING_SMRAM, &(smram[1]));
mem_mapping_disable(&ram_smram_mapping[0]);
mem_mapping_disable(&ram_smram_mapping[1]);
mem_mapping_add(&ram_remapped_mapping, mem_size * 1024, 256 * 1024, mem_mapping_add(&ram_remapped_mapping, mem_size * 1024, 256 * 1024,
mem_read_remapped,mem_read_remappedw,mem_read_remappedl, mem_read_remapped,mem_read_remappedw,mem_read_remappedl,
@@ -2476,6 +2738,9 @@ mem_log("MEM: reset: new pages=%08lx, pages_sz=%i\n", pages, pages_sz);
mem_a20_init(); mem_a20_init();
smram[0].host_base = smram[0].ram_base = 0x00000000;
smram[1].host_base = smram[1].ram_base = 0x00000000;
#ifdef USE_NEW_DYNAREC #ifdef USE_NEW_DYNAREC
purgable_page_list_head = 0; purgable_page_list_head = 0;
purgeable_page_count = 0; purgeable_page_count = 0;
@@ -2488,6 +2753,7 @@ mem_init(void)
{ {
/* Perform a one-time init. */ /* Perform a one-time init. */
ram = rom = NULL; ram = rom = NULL;
ram2 = NULL;
pages = NULL; pages = NULL;
#if DYNAMIC_TABLES #if DYNAMIC_TABLES
page_lookup = NULL; page_lookup = NULL;
@@ -2515,7 +2781,7 @@ mem_init(void)
void void
mem_remap_top(int kb) mem_remap_top(int kb)
{ {
int c; uint32_t c;
uint32_t start = (mem_size >= 1024) ? mem_size : 1024; uint32_t start = (mem_size >= 1024) ? mem_size : 1024;
int offset, size = mem_size - 640; int offset, size = mem_size - 640;
@@ -2545,8 +2811,8 @@ mem_remap_top(int kb)
#endif #endif
} }
mem_set_mem_state(start * 1024, size * 1024, mem_set_mem_state_both(start * 1024, size * 1024,
MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
mem_mapping_set_addr(&ram_remapped_mapping, start * 1024, size * 1024); mem_mapping_set_addr(&ram_remapped_mapping, start * 1024, size * 1024);
mem_mapping_set_exec(&ram_remapped_mapping, ram + (start * 1024)); mem_mapping_set_exec(&ram_remapped_mapping, ram + (start * 1024));

View File

@@ -31,8 +31,8 @@
#include <86box/pic.h> #include <86box/pic.h>
#include <86box/mem.h> #include <86box/mem.h>
#include <86box/device.h> #include <86box/device.h>
#include <86box/dma.h>
#include <86box/pci.h> #include <86box/pci.h>
#include <86box/piix.h>
#include <86box/keyboard.h> #include <86box/keyboard.h>

View File

@@ -516,7 +516,7 @@ MAINOBJ := pc.o config.o random.o timer.o io.o acpi.o apm.o dma.o ddma.o \
usb.o device.o nvr.o nvr_at.o nvr_ps2.o sst_flash.o via_vt82c586b.o \ usb.o device.o nvr.o nvr_at.o nvr_ps2.o sst_flash.o via_vt82c586b.o \
via_vt82c596b.o $(VNCOBJ) via_vt82c596b.o $(VNCOBJ)
INTELOBJ := intel_flash.o \ INTELOBJ := intel_flash.o intel_420ex.o \
intel_sio.o intel_piix.o intel_sio.o intel_piix.o
CPUOBJ := cpu.o cpu_table.o \ CPUOBJ := cpu.o cpu_table.o \

View File

@@ -520,7 +520,7 @@ MAINOBJ := pc.o config.o random.o timer.o io.o acpi.o apm.o dma.o ddma.o \
usb.o device.o nvr.o nvr_at.o nvr_ps2.o sst_flash.o via_vt82c586b.o \ usb.o device.o nvr.o nvr_at.o nvr_ps2.o sst_flash.o via_vt82c586b.o \
via_vt82c596b.o $(VNCOBJ) via_vt82c596b.o $(VNCOBJ)
INTELOBJ := intel_flash.o \ INTELOBJ := intel_flash.o intel_420ex.o \
intel_sio.o intel_piix.o intel_sio.o intel_piix.o
CPUOBJ := cpu.o cpu_table.o \ CPUOBJ := cpu.o cpu_table.o \