diff --git a/src/chipset/via_apollo.c b/src/chipset/via_apollo.c index a3200669a..929759fe0 100644 --- a/src/chipset/via_apollo.c +++ b/src/chipset/via_apollo.c @@ -32,6 +32,7 @@ #include <86box/device.h> #include <86box/keyboard.h> #include <86box/chipset.h> +#include <86box/spd.h> typedef struct via_apollo_t @@ -226,6 +227,13 @@ via_apollo_host_bridge_write(int func, int addr, uint8_t val, void *priv) dev->pci_conf[0][0x53] = (dev->pci_conf[0][0x53] & ~0xf0) | (val & 0xf0); break; + case 0x56: case 0x57: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f: /* DRAM Row Ending Address */ + if (dev->id >= 0x0691) + spd_write_drbs(dev->pci_conf[0], 0x5a, 0x56, 8); + else if (addr >= 0x5a) + spd_write_drbs(dev->pci_conf[0], 0x5a, 0x5f, 8); + break; + case 0x58: if (dev->id == 0x0597) dev->pci_conf[0][0x58] = (dev->pci_conf[0][0x58] & ~0xee) | (val & 0xee); diff --git a/src/mem/spd.c b/src/mem/spd.c index 6399fd1f0..d9dc5c370 100644 --- a/src/mem/spd.c +++ b/src/mem/spd.c @@ -407,10 +407,14 @@ spd_register(uint8_t ram_type, uint8_t slot_mask, uint16_t max_module_size) void spd_write_drbs(uint8_t *regs, uint8_t reg_min, uint8_t reg_max, uint8_t drb_unit) { - uint8_t row, dimm; + uint8_t row, dimm, drb, apollo = 0; uint16_t size, vslots[SPD_MAX_SLOTS]; - spd_log("DRB write begin\n"); + /* Special case for VIA Apollo Pro family, which jumps from 5F to 56. */ + if (reg_max < reg_min) { + apollo = reg_max; + reg_max = reg_min + 8; + } /* No SPD: split SIMMs into pairs as if they were "DIMM"s. */ if (!spd_present) { @@ -437,11 +441,16 @@ spd_write_drbs(uint8_t *regs, uint8_t reg_min, uint8_t reg_max, uint8_t drb_unit size = (vslots[dimm] >> 1); } - /* Populate DRB register, adding the previous DRB's value. + /* Determine the DRB register to write. */ + drb = reg_min + row; + if ((apollo) && ((drb & 0xf) < 0x8)) + drb = apollo + (drb & 0xf); + + /* Write 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); + regs[drb] = ((row > 0) ? regs[drb - 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]); + regs[drb] += (size / drb_unit); + spd_log("DRB[%d] = %d MB (%02Xh raw)\n", row, size, regs[drb]); } }