Unified DRB locking logic, added DRB locking to VIA VPX, and fixed SPD

This commit is contained in:
RichardG867
2020-06-26 21:03:46 -03:00
parent 84e378695a
commit 2553dbce8f
6 changed files with 59 additions and 82 deletions

View File

@@ -180,33 +180,6 @@ i420ex_smram_handler_phase1(i420ex_t *dev)
} }
static void
i420ex_write_drbs(i420ex_t *dev)
{
uint8_t row, dimm;
uint16_t size, vslots[SPD_MAX_SLOTS];
/* No SPD: let the SPD code split SIMMs into pairs as if they were "DIMM"s. */
dimm = (4 + 1) >> 1; /* amount of "DIMM"s, also used to determine the maximum "DIMM" size */
spd_populate(vslots, dimm, (mem_size >> 10), 1, 1 << (log2_ui16(machines[machine].max_ram / dimm)), 0);
/* Write DRBs for each row. */
i420ex_log("Writing DRBs...\n");
for (row = 0; row <= 4; row++) {
dimm = (row >> 1);
/* No SPD: use the values calculated above. */
size = (vslots[dimm] >> 1);
/* Populate DRB register, adding the previous DRB's value.. */
dev->regs[0x60 | row] = ((row > 0) ? dev->regs[0x60 | (row - 1)] : 0);
if (size)
dev->regs[0x60 | row] += size;
i420ex_log("DRB[%d] = %d MB (%02Xh raw)\n", row, size, dev->regs[0x60 | row]);
}
}
static void static void
i420ex_write(int func, int addr, uint8_t val, void *priv) i420ex_write(int func, int addr, uint8_t val, void *priv)
{ {
@@ -333,7 +306,7 @@ i420ex_write(int func, int addr, uint8_t val, void *priv)
dev->regs[0x5f] = val; dev->regs[0x5f] = val;
break; break;
case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x60: case 0x61: case 0x62: case 0x63: case 0x64:
i420ex_write_drbs(dev); spd_write_drbs(dev->regs, 0x60, 0x64, 1);
break; break;
case 0x66: case 0x67: case 0x66: case 0x67:
i420ex_log("Set IRQ routing: INT %c -> %02X\n", 0x41 + (addr & 0x01), val); i420ex_log("Set IRQ routing: INT %c -> %02X\n", 0x41 + (addr & 0x01), val);

View File

@@ -29,7 +29,6 @@
#include <86box/keyboard.h> #include <86box/keyboard.h>
#include <86box/chipset.h> #include <86box/chipset.h>
#include <86box/spd.h> #include <86box/spd.h>
#include <86box/machine.h>
enum enum
@@ -269,47 +268,6 @@ pm2_cntrl_write(uint16_t addr, uint8_t val, void *p)
} }
static void
i4x0_write_drbs(i4x0_t *dev)
{
uint8_t row, dimm;
uint16_t size, vslots[SPD_MAX_SLOTS];
/* No SPD: let the SPD code split SIMMs into pairs as if they were "DIMM"s. */
if (!spd_present) {
dimm = (dev->max_drb + 1) >> 1; /* amount of "DIMM"s, also used to determine the maximum "DIMM" size */
spd_populate(vslots, dimm, (mem_size >> 10), dev->drb_unit, 1 << (log2_ui16(machines[machine].max_ram / dimm)), 0);
}
/* Write DRBs for each row. */
i4x0_log("Writing DRBs... unit=%d max=%d\n", dev->drb_unit, dev->max_drb);
for (row = 0; row <= dev->max_drb; row++) {
dimm = (row >> 1);
size = 0;
if (spd_present) {
/* SPD enabled: use SPD info for this slot, if present. */
if (spd_devices[dimm]) {
if (spd_devices[dimm]->row1 < dev->drb_unit) /* hack within a hack: turn a double-sided DIMM that is too small into a single-sided one */
size = ((row & 1) ? 0 : dev->drb_unit);
else
size = ((row & 1) ? spd_devices[dimm]->row2 : spd_devices[dimm]->row1);
}
} else {
/* No SPD: use the values calculated above. */
size = (vslots[dimm] >> 1);
}
/* Populate DRB register, adding the previous DRB's value.
This will intentionally overflow on 440GX with 2 GB. */
dev->regs[0][0x60 | row] = ((row > 0) ? dev->regs[0][0x60 | (row - 1)] : 0);
if (size)
dev->regs[0][0x60 | row] += (size / dev->drb_unit);
i4x0_log("DRB[%d] = %d MB (%02Xh raw)\n", row, size, dev->regs[0][0x60 | row]);
}
}
static void static void
i4x0_write(int func, int addr, uint8_t val, void *priv) i4x0_write(int func, int addr, uint8_t val, void *priv)
{ {
@@ -692,7 +650,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
break; break;
case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x60: case 0x61: case 0x62: case 0x63: case 0x64:
if ((addr & 0x7) <= dev->max_drb) { if ((addr & 0x7) <= dev->max_drb) {
i4x0_write_drbs(dev); spd_write_drbs(regs, 0x60, 0x60 + dev->max_drb, dev->drb_unit);
break; break;
} }
switch (dev->type) { switch (dev->type) {
@@ -715,7 +673,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
break; break;
case 0x65: case 0x65:
if ((addr & 0x7) <= dev->max_drb) { if ((addr & 0x7) <= dev->max_drb) {
i4x0_write_drbs(dev); spd_write_drbs(regs, 0x60, 0x60 + dev->max_drb, dev->drb_unit);
break; break;
} }
switch (dev->type) { switch (dev->type) {
@@ -738,7 +696,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
break; break;
case 0x66: case 0x66:
if ((addr & 0x7) <= dev->max_drb) { if ((addr & 0x7) <= dev->max_drb) {
i4x0_write_drbs(dev); spd_write_drbs(regs, 0x60, 0x60 + dev->max_drb, dev->drb_unit);
break; break;
} }
switch (dev->type) { switch (dev->type) {
@@ -752,7 +710,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
break; break;
case 0x67: case 0x67:
if ((addr & 0x7) <= dev->max_drb) { if ((addr & 0x7) <= dev->max_drb) {
i4x0_write_drbs(dev); spd_write_drbs(regs, 0x60, 0x60 + dev->max_drb, dev->drb_unit);
break; break;
} }
switch (dev->type) { switch (dev->type) {

View File

@@ -35,6 +35,7 @@
#include <86box/device.h> #include <86box/device.h>
#include <86box/keyboard.h> #include <86box/keyboard.h>
#include <86box/chipset.h> #include <86box/chipset.h>
#include <86box/spd.h>
typedef struct via_vpx_t typedef struct via_vpx_t
{ {
@@ -94,6 +95,10 @@ via_vpx_t *dev = (via_vpx_t *) priv;
dev->pci_conf[0x07] &= ~(val & 0xb0); dev->pci_conf[0x07] &= ~(val & 0xb0);
break; break;
case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f: // Bank Ending
spd_write_drbs(dev->pci_conf, 0x5a, 0x5f, 4);
break;
case 0x61: // Shadow RAM control 1 case 0x61: // Shadow RAM control 1
if ((dev->pci_conf[0x61] ^ val) & 0x03) if ((dev->pci_conf[0x61] ^ val) & 0x03)
vpx_map(0xc0000, 0x04000, val & 0x03); vpx_map(0xc0000, 0x04000, val & 0x03);
@@ -201,6 +206,7 @@ via_vpx_init(const device_t *info)
dev->pci_conf[0x5e] = 1; // Bank 4 Ending dev->pci_conf[0x5e] = 1; // Bank 4 Ending
dev->pci_conf[0x5f] = 1; // Bank 5 Ending dev->pci_conf[0x5f] = 1; // Bank 5 Ending
dev->pci_conf[0x60] = 0x3f; // DRAM type
dev->pci_conf[0x64] = 0xab; // DRAM reference timing dev->pci_conf[0x64] = 0xab; // DRAM reference timing
return dev; return dev;

View File

@@ -100,13 +100,8 @@ typedef struct _spd_sdram_ {
} spd_sdram_t; } spd_sdram_t;
extern int spd_present;
extern spd_t *spd_devices[SPD_MAX_SLOTS];
extern uint8_t log2_ui16(uint16_t i);
extern void spd_populate(uint16_t *vslots, uint8_t slot_count, uint16_t total_size, uint16_t min_module_size, uint16_t max_module_size, uint8_t enable_asym);
extern void spd_register(uint8_t ram_type, uint8_t slot_mask, uint16_t max_module_size); extern void spd_register(uint8_t ram_type, uint8_t slot_mask, uint16_t max_module_size);
extern void spd_write_drbs(uint8_t *regs, uint8_t reg_min, uint8_t reg_max, uint8_t drb_unit);
#endif /*EMU_SPD_H*/ #endif /*EMU_SPD_H*/

View File

@@ -983,6 +983,7 @@ machine_at_ficva502_init(const machine_t *model)
device_add(&keyboard_ps2_pci_device); device_add(&keyboard_ps2_pci_device);
device_add(&fdc37c669_device); device_add(&fdc37c669_device);
device_add(&sst_flash_29ee010_device); device_add(&sst_flash_29ee010_device);
spd_register(SPD_TYPE_SDRAM, 0x7, 256);
return ret; return ret;
} }

View File

@@ -26,6 +26,7 @@
#include <86box/smbus.h> #include <86box/smbus.h>
#include <86box/spd.h> #include <86box/spd.h>
#include <86box/version.h> #include <86box/version.h>
#include <86box/machine.h>
#define MIN(a, b) ((a) < (b) ? (a) : (b)) #define MIN(a, b) ((a) < (b) ? (a) : (b))
@@ -41,7 +42,7 @@ static uint8_t spd_read_byte(uint8_t addr, void *priv);
static uint8_t spd_read_byte_cmd(uint8_t addr, uint8_t cmd, void *priv); static uint8_t spd_read_byte_cmd(uint8_t addr, uint8_t cmd, void *priv);
static void spd_write_byte(uint8_t addr, uint8_t val, void *priv); static void spd_write_byte(uint8_t addr, uint8_t val, void *priv);
#define ENABLE_SPD_LOG 1
#ifdef ENABLE_SPD_LOG #ifdef ENABLE_SPD_LOG
int spd_do_log = ENABLE_SPD_LOG; int spd_do_log = ENABLE_SPD_LOG;
@@ -397,7 +398,50 @@ spd_register(uint8_t ram_type, uint8_t slot_mask, uint16_t max_module_size)
break; break;
} }
//device_add(info); device_add(info);
vslot++; vslot++;
} }
} }
void
spd_write_drbs(uint8_t *regs, uint8_t reg_min, uint8_t reg_max, uint8_t drb_unit)
{
uint8_t row, dimm;
uint16_t size, vslots[SPD_MAX_SLOTS];
spd_log("DRB write begin\n");
/* No SPD: split SIMMs into pairs as if they were "DIMM"s. */
if (!spd_present) {
dimm = ((reg_max - reg_min) + 1) >> 1; /* amount of "DIMM"s, also used to determine the maximum "DIMM" size */
spd_populate(vslots, dimm, (mem_size >> 10), drb_unit, 1 << (log2_ui16(machines[machine].max_ram / dimm)), 0);
}
/* Write DRBs for each row. */
spd_log("Writing DRBs... regs=[%02X:%02X] unit=%d\n", reg_min, reg_max, drb_unit);
for (row = 0; row <= (reg_max - reg_min); row++) {
dimm = (row >> 1);
size = 0;
if (spd_present) {
/* SPD enabled: use SPD info for this slot, if present. */
if (spd_devices[dimm]) {
if (spd_devices[dimm]->row1 < drb_unit) /* hack within a hack: turn a double-sided DIMM that is too small into a single-sided one */
size = ((row & 1) ? 0 : drb_unit);
else
size = ((row & 1) ? spd_devices[dimm]->row2 : spd_devices[dimm]->row1);
}
} else {
/* No SPD: use the values calculated above. */
size = (vslots[dimm] >> 1);
}
/* Populate DRB register, adding the previous DRB's value.
This will intentionally overflow on 440GX with 2 GB. */
regs[reg_min + row] = ((row > 0) ? regs[reg_min + row - 1] : 0);
if (size)
regs[reg_min + row] += (size / drb_unit);
spd_log("DRB[%d] = %d MB (%02Xh raw)\n", row, size, regs[reg_min + row]);
}
}