From adc3349c1ce6da3e6e2a483c822d7f5e375f53c9 Mon Sep 17 00:00:00 2001 From: Patrick Mackinlay Date: Mon, 17 Jul 2023 11:47:09 +0700 Subject: sgi/mc: memory controller ram configuration improvements --- src/mame/sgi/indigo.cpp | 34 ++------- src/mame/sgi/indy_indigo2.cpp | 38 +++------- src/mame/sgi/mc.cpp | 158 ++++++++++++++++++++++++++++++++++++++++-- src/mame/sgi/mc.h | 11 ++- 4 files changed, 176 insertions(+), 65 deletions(-) diff --git a/src/mame/sgi/indigo.cpp b/src/mame/sgi/indigo.cpp index 3bd25bad1d3..b97d08db259 100644 --- a/src/mame/sgi/indigo.cpp +++ b/src/mame/sgi/indigo.cpp @@ -90,7 +90,6 @@ public: : indigo_state(mconfig, type, tag) , m_maincpu(*this, "maincpu") , m_mem_ctrl(*this, "memctrl") - , m_share1(*this, "share1") { } @@ -101,11 +100,8 @@ protected: void mem_map(address_map &map); - void write_ram(offs_t offset, uint64_t data, uint64_t mem_mask = ~0); - required_device m_maincpu; required_device m_mem_ctrl; - required_shared_ptr m_share1; }; void indigo_state::machine_start() @@ -121,9 +117,6 @@ void indigo_state::machine_reset() void indigo4k_state::machine_reset() { indigo_state::machine_reset(); - - // set up low RAM mirror - membank("bank1")->set_base(m_share1); } uint32_t indigo_state::int_r(offs_t offset, uint32_t mem_mask) @@ -164,32 +157,11 @@ void indigo3k_state::mem_map(address_map &map) map(0x1fc00000, 0x1fc3ffff).rom().region("user1", 0); } -void indigo4k_state::write_ram(offs_t offset, uint64_t data, uint64_t mem_mask) -{ - // if banks 2 or 3 are enabled, do nothing, we don't support that much memory - if (m_mem_ctrl->get_mem_config(1) & 0x10001000) - { - // a random perturbation so the memory test fails - data ^= 0xffffffffffffffffULL; - } - - // if banks 0 or 1 have 2 membanks, also kill it, we only want 128 MB - if (m_mem_ctrl->get_mem_config(0) & 0x40004000) - { - // a random perturbation so the memory test fails - data ^= 0xffffffffffffffffULL; - } - COMBINE_DATA(&m_share1[offset]); -} - void indigo4k_state::mem_map(address_map &map) { indigo_map(map); - map(0x00000000, 0x0007ffff).bankrw("bank1"); - map(0x08000000, 0x17ffffff).ram().share("share1").w(FUNC(indigo4k_state::write_ram)); /* 256 MB of main RAM */ map(0x1fa00000, 0x1fa1ffff).rw(m_mem_ctrl, FUNC(sgi_mc_device::read), FUNC(sgi_mc_device::write)); map(0x1fc00000, 0x1fc7ffff).rom().region("user1", 0); - map(0x20000000, 0x2fffffff).ram().share("share1").w(FUNC(indigo4k_state::write_ram)); /* 256 MB of main RAM */ } static INPUT_PORTS_START(indigo) @@ -213,6 +185,10 @@ void indigo3k_state::indigo3k(machine_config &config) SGI_HPC1(config, m_hpc, m_maincpu, m_eeprom); } +static DEVICE_INPUT_DEFAULTS_START(ip20_mc) + DEVICE_INPUT_DEFAULTS("VALID", 0x0f, 0x07) +DEVICE_INPUT_DEFAULTS_END + void indigo4k_state::indigo4k(machine_config &config) { indigo_base(config); @@ -224,6 +200,8 @@ void indigo4k_state::indigo4k(machine_config &config) SGI_MC(config, m_mem_ctrl, m_maincpu, m_eeprom, 50000000); m_mem_ctrl->eisa_present().set_constant(0); + m_mem_ctrl->set_input_default(DEVICE_INPUT_DEFAULTS_NAME(ip20_mc)); + SGI_HPC1(config, m_hpc, m_maincpu, m_eeprom); } diff --git a/src/mame/sgi/indy_indigo2.cpp b/src/mame/sgi/indy_indigo2.cpp index c0fcbdfe229..6c56f4e0eef 100644 --- a/src/mame/sgi/indy_indigo2.cpp +++ b/src/mame/sgi/indy_indigo2.cpp @@ -89,7 +89,6 @@ public: ip24_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag) , m_maincpu(*this, "maincpu") - , m_mainram(*this, "mainram") , m_mem_ctrl(*this, "memctrl") , m_scsi_ctrl(*this, "scsibus:0:wd33c93") , m_edlc(*this, "edlc") @@ -117,7 +116,6 @@ protected: virtual void machine_start() override; virtual void machine_reset() override; - void write_ram(offs_t offset, uint64_t data, uint64_t mem_mask = ~0); template uint64_t bus_error_r(offs_t offset, uint64_t mem_mask = ~0); template void bus_error_w(offs_t offset, uint64_t data, uint64_t mem_mask = ~0); @@ -138,7 +136,6 @@ protected: static void scsi_devices(device_slot_interface &device); required_device m_maincpu; - required_shared_ptr m_mainram; required_device m_mem_ctrl; required_device m_scsi_ctrl; required_device m_edlc; @@ -203,25 +200,6 @@ uint32_t ip22_state::eisa_io_r() return 0xffffffff; } -// a bit hackish, but makes the memory detection work properly and allows a big cleanup of the mapping -void ip24_state::write_ram(offs_t offset, uint64_t data, uint64_t mem_mask) -{ - // if banks 2 or 3 are enabled, do nothing, we don't support that much memory - if (m_mem_ctrl->get_mem_config(1) & 0x10001000) - { - // a random perturbation so the memory test fails - data ^= 0xffffffffffffffffULL; - } - - // if banks 0 or 1 have 2 membanks, also kill it, we only want 128 MB - if (m_mem_ctrl->get_mem_config(0) & 0x40004000) - { - // a random perturbation so the memory test fails - data ^= 0xffffffffffffffffULL; - } - COMBINE_DATA(&m_mainram[offset]); -} - uint8_t ip24_state::volume_r(offs_t offset) { if (offset == 0) @@ -246,14 +224,11 @@ void ip24_state::volume_w(offs_t offset, uint8_t data) void ip24_state::ip24_base_map(address_map &map) { - map(0x00000000, 0x0007ffff).bankrw("bank1"); /* mirror of first 512k of main RAM */ - map(0x08000000, 0x0fffffff).share("mainram").ram().w(FUNC(ip24_state::write_ram)); /* 128 MB of main RAM */ map(0x1f000000, 0x1f9fffff).rw(m_gio64, FUNC(gio64_device::read), FUNC(gio64_device::write)); map(0x1fa00000, 0x1fa1ffff).rw(m_mem_ctrl, FUNC(sgi_mc_device::read), FUNC(sgi_mc_device::write)); map(0x1fb00000, 0x1fb7ffff).rw(FUNC(ip24_state::bus_error_r<0x1fb00000>), FUNC(ip24_state::bus_error_w<0x1fb00000>)); map(0x1fb80000, 0x1fbfffff).m(m_hpc3, FUNC(hpc3_device::map)); map(0x1fc00000, 0x1fc7ffff).rom().region("user1", 0); - map(0x20000000, 0x27ffffff).share("mainram").ram().w(FUNC(ip24_state::write_ram)); } void ip24_state::ip24_map(address_map &map) @@ -306,9 +281,6 @@ void ip24_state::machine_start() void ip24_state::machine_reset() { - // set up low RAM mirror - membank("bank1")->set_base(m_mainram); - //m_maincpu->mips3drc_set_options(MIPS3DRC_COMPATIBLE_OPTIONS | MIPS3DRC_CHECK_OVERFLOWS); } @@ -329,6 +301,14 @@ void ip24_state::scsi_devices(device_slot_interface &device) //device.set_option_machine_config("cdrom", cdrom_config); } +static DEVICE_INPUT_DEFAULTS_START(ip22_mc) + DEVICE_INPUT_DEFAULTS("VALID", 0x0f, 0x07) +DEVICE_INPUT_DEFAULTS_END + +static DEVICE_INPUT_DEFAULTS_START(ip24_mc) + DEVICE_INPUT_DEFAULTS("VALID", 0x0f, 0x03) +DEVICE_INPUT_DEFAULTS_END + void ip24_state::ip24_base(machine_config &config, uint32_t system_clock) { SGI_MC(config, m_mem_ctrl, m_maincpu, m_eeprom, system_clock); @@ -390,6 +370,7 @@ void ip24_state::ip24_base(machine_config &config, uint32_t system_clock) void ip24_state::ip24(machine_config &config, uint32_t system_clock) { ip24_base(config, system_clock); + m_mem_ctrl->set_input_default(DEVICE_INPUT_DEFAULTS_NAME(ip24_mc)); m_hpc3->set_addrmap(hpc3_device::AS_PIO6, &ip24_state::pio6_map); @@ -456,6 +437,7 @@ void ip22_state::indigo2_4415(machine_config &config) m_maincpu->set_addrmap(AS_PROGRAM, &ip22_state::ip22_map); ip24_base(config, system_clock); + m_mem_ctrl->set_input_default(DEVICE_INPUT_DEFAULTS_NAME(ip22_mc)); NSCSI_BUS(config, "scsibus2", 0); NSCSI_CONNECTOR(config, "scsibus2:0").option_set("wd33c93", WD33C93B) diff --git a/src/mame/sgi/mc.cpp b/src/mame/sgi/mc.cpp index c7ac810fd9c..79186754faf 100644 --- a/src/mame/sgi/mc.cpp +++ b/src/mame/sgi/mc.cpp @@ -31,6 +31,7 @@ sgi_mc_device::sgi_mc_device(const machine_config &mconfig, const char *tag, dev : device_t(mconfig, SGI_MC, tag, owner, clock) , m_maincpu(*this, finder_base::DUMMY_TAG) , m_eeprom(*this, finder_base::DUMMY_TAG) + , m_simms(*this, "SIMMS") , m_int_dma_done_cb(*this) , m_eisa_present(*this, true) , m_dma_timer(nullptr) @@ -43,6 +44,7 @@ sgi_mc_device::sgi_mc_device(const machine_config &mconfig, const char *tag, dev , m_gio64_arb_param(0) , m_arb_cpu_time(0) , m_arb_burst_time(0) + , m_memcfg{} , m_cpu_mem_access_config(0) , m_gio_mem_access_config(0) , m_cpu_error_addr(0) @@ -90,7 +92,7 @@ void sgi_mc_device::device_start() save_item(NAME(m_gio64_arb_param)); save_item(NAME(m_arb_cpu_time)); save_item(NAME(m_arb_burst_time)); - save_item(NAME(m_mem_config)); + save_item(NAME(m_memcfg)); save_item(NAME(m_cpu_mem_access_config)); save_item(NAME(m_gio_mem_access_config)); save_item(NAME(m_cpu_error_addr)); @@ -129,8 +131,6 @@ void sgi_mc_device::device_reset() m_gio64_arb_param = 0; m_arb_cpu_time = 0; m_arb_burst_time = 0; - m_mem_config[0] = 0; - m_mem_config[1] = 0; m_cpu_mem_access_config = 0; m_gio_mem_access_config = 0; m_cpu_error_addr = 0; @@ -161,6 +161,31 @@ void sgi_mc_device::device_reset() memset(m_semaphore, 0, sizeof(uint32_t) * 16); m_space = &m_maincpu->space(AS_PROGRAM); + + u16 const simms = m_simms->read(); + + // allocate installed memory + for (unsigned bank = 0; bank < 4; bank++) + { + u32 const size = BIT(simms, bank * 4, 3); + + switch (size) + { + case 0: + LOG("ram bank %c empty\n", bank + 'A'); + m_ram[bank].reset(); + break; + default: + LOG("ram bank %c size %dM (%s rank)\n", + bank + 'A', 1U << (size + 1), BIT(simms, bank * 4 + 3) ? "dual" : "single"); + m_ram[bank] = std::make_unique(1U << (size + 21)); + break; + } + } + + // assume memory configuration is invalidated by reset + memcfg_w(0, 0); + memcfg_w(1, 0); } void sgi_mc_device::set_cpu_buserr(uint32_t address, uint64_t mem_mask) @@ -351,8 +376,8 @@ uint32_t sgi_mc_device::read(offs_t offset, uint32_t mem_mask) case 0x00c8/4: { const uint32_t index = (offset >> 1) & 1; - LOGMASKED(LOG_MEMCFG, "%s: Memory Configuration Register %d Read: %08x & %08x\n", machine().describe_context(), index, m_mem_config[index], mem_mask); - return m_mem_config[index]; + LOGMASKED(LOG_MEMCFG, "%s: Memory Configuration Register %d Read: %08x & %08x\n", machine().describe_context(), index, m_memcfg[index], mem_mask); + return m_memcfg[index]; } case 0x00d0/4: LOGMASKED(LOG_READS, "%s: CPU Memory Access Config Params Read: %08x & %08x\n", machine().describe_context(), m_cpu_mem_access_config, mem_mask); @@ -545,7 +570,7 @@ void sgi_mc_device::write(offs_t offset, uint32_t data, uint32_t mem_mask) LOGMASKED(LOG_MEMCFG_EXT, "%s: Bank %d, SIMM Size: %02x (%s)\n", machine().describe_context(), index+1, (data >> 8) & 0x1f, s_mem_size[(data >> 8) & 0x1f]); LOGMASKED(LOG_MEMCFG_EXT, "%s: Bank %d, Valid: %d\n", machine().describe_context(), index+1, BIT(data, 13)); LOGMASKED(LOG_MEMCFG_EXT, "%s: Bank %d, # Subbanks: %d\n", machine().describe_context(), index+1, BIT(data, 14) + 1); - m_mem_config[index] = data; + memcfg_w(index, data); break; } case 0x00d0/4: @@ -713,3 +738,124 @@ void sgi_mc_device::write(offs_t offset, uint32_t data, uint32_t mem_mask) break; } } + +/* + * When the configured memory size for a bank exceeds the physical memory + * installed in the bank, the physical memory is mirrored in the configured + * range. When dual ranks are configured, the configured space is divided in + * two and each rank of the installed memory mirrored in the corresponding + * half. When the configured and installed number of ranks do not match, either + * half of the installed memory will be inaccessible, or half of the configured + * range will not be mapped to anything. + * + * The lowest 512KiB of whatever is mapped into physical memory segment 0 + * (address 0x0800'0000) is also mapped at address 0. + */ +void sgi_mc_device::memcfg_w(offs_t offset, u32 data) +{ + LOGMASKED(LOG_MEMCFG, "memcfg%d 0x%08x\n", offset, data); + + // remove existing mapping + for (unsigned bank = 0; bank < 2; bank++) + { + // if previous memory configuration was valid, unmap the whole configured range + if (BIT(m_memcfg[offset], 29 - bank * 16)) + { + u32 const conf_base = BIT(m_memcfg[offset], 16 - bank * 16, 8) << 22; + u32 const conf_size = (BIT(m_memcfg[offset], 24 - bank * 16, 5) + 1) << 22; + + LOGMASKED(LOG_MEMCFG, "unmap bank %c 0x%08x-0x%08x\n", + offset * 2 + bank + 'A', conf_base, conf_base + conf_size - 1); + m_space->unmap_readwrite(conf_base, conf_base + conf_size - 1); + + if (conf_base == 0x0800'0000U) + m_space->unmap_readwrite(0x0000'0000, 0x0007'ffff); + } + } + + m_memcfg[offset] = data; + + u16 const simms = m_simms->read(); + + // install ram into memory map + for (unsigned bank = 0; bank < 2; bank++) + { + // bank configuration valid? + if (!BIT(m_memcfg[offset], 29 - bank * 16)) + continue; + + // simms installed in bank? + if (!BIT(simms, (offset * 2 + bank) * 4, 3)) + continue; + + // configured base, rank and size/rank + u32 const conf_base = BIT(m_memcfg[offset], 16 - bank * 16, 8) << 22; + unsigned const conf_rank = BIT(m_memcfg[offset], 30 - bank * 16); + u32 const conf_size = (BIT(m_memcfg[offset], 24 - bank * 16, 5) + 1) << (22 - conf_rank); + + // installed rank and size/rank + unsigned const inst_rank = BIT(simms, (offset * 2 + bank) * 4 + 3); + u32 const inst_size = 1U << (BIT(simms, (offset * 2 + bank) * 4, 3) + 21 - inst_rank); + + // resulting number of ranks and size/rank + unsigned const ranks = std::min(conf_rank, inst_rank) + 1; + u32 const size = std::min(conf_size, inst_size); + + for (unsigned rank = 0; rank < ranks; rank++) + { + LOGMASKED(LOG_MEMCFG, "remap bank %c rank %d from 0x%08x-0x%08x mirror 0x%08x size 0x%08x offset 0x%08x\n", + offset * 2 + bank + 'A', rank, conf_base + conf_size * rank, conf_base + conf_size * rank + size - 1, (conf_size - 1) ^ (size - 1), size, size * rank); + m_space->install_ram(conf_base + conf_size * rank, conf_base + conf_size * rank + size - 1, (conf_size - 1) ^ (size - 1), &m_ram[offset * 2 + bank][size * rank]); + } + + if (conf_base == 0x0800'0000U) + m_space->install_ram(0x0000'0000, 0x0007'ffff, &m_ram[offset * 2 + bank][0]); + } +} + +static INPUT_PORTS_START(mc) + PORT_START("VALID") + PORT_CONFNAME(0x0f, 0x00, "Valid Banks") + + PORT_START("SIMMS") + PORT_CONFNAME(0x000f, 0x0003, "RAM bank A") PORT_CONDITION("VALID", 0x01, EQUALS, 0x01) + PORT_CONFSETTING(0x0000, "Empty") + PORT_CONFSETTING(0x0001, "4x1M") + PORT_CONFSETTING(0x000a, "4x2M") + PORT_CONFSETTING(0x0003, "4x4M") + PORT_CONFSETTING(0x000c, "4x8M") + PORT_CONFSETTING(0x0005, "4x16M") + PORT_CONFSETTING(0x000e, "4x32M") + + PORT_CONFNAME(0x00f0, 0x0000, "RAM bank B") PORT_CONDITION("VALID", 0x02, EQUALS, 0x02) + PORT_CONFSETTING(0x0000, "Empty") + PORT_CONFSETTING(0x0010, "4x1M") + PORT_CONFSETTING(0x00a0, "4x2M") + PORT_CONFSETTING(0x0030, "4x4M") + PORT_CONFSETTING(0x00c0, "4x8M") + PORT_CONFSETTING(0x0050, "4x16M") + PORT_CONFSETTING(0x00e0, "4x32M") + + PORT_CONFNAME(0x0f00, 0x0000, "RAM bank C") PORT_CONDITION("VALID", 0x04, EQUALS, 0x04) + PORT_CONFSETTING(0x0000, "Empty") + PORT_CONFSETTING(0x0100, "4x1M") + PORT_CONFSETTING(0x0a00, "4x2M") + PORT_CONFSETTING(0x0300, "4x4M") + PORT_CONFSETTING(0x0c00, "4x8M") + PORT_CONFSETTING(0x0500, "4x16M") + PORT_CONFSETTING(0x0e00, "4x32M") + + PORT_CONFNAME(0xf000, 0x0000, "RAM bank D") PORT_CONDITION("VALID", 0x08, EQUALS, 0x08) + PORT_CONFSETTING(0x0000, "Empty") + PORT_CONFSETTING(0x1000, "4x1M") + PORT_CONFSETTING(0xa000, "4x2M") + PORT_CONFSETTING(0x3000, "4x4M") + PORT_CONFSETTING(0xc000, "4x8M") + PORT_CONFSETTING(0x5000, "4x16M") + PORT_CONFSETTING(0xe000, "4x32M") +INPUT_PORTS_END + +ioport_constructor sgi_mc_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(mc); +} diff --git a/src/mame/sgi/mc.h b/src/mame/sgi/mc.h index 2ab777fe4ce..b376ecc0a7a 100644 --- a/src/mame/sgi/mc.h +++ b/src/mame/sgi/mc.h @@ -34,12 +34,12 @@ public: void write(offs_t offset, uint32_t data, uint32_t mem_mask = ~0); void set_cpu_buserr(uint32_t address, uint64_t mem_mask); - uint32_t get_mem_config(int channel) const { return m_mem_config[channel]; } protected: // device_t implementation virtual void device_start() override; virtual void device_reset() override; + virtual ioport_constructor device_input_ports() const override; private: enum @@ -63,9 +63,13 @@ private: void update_count(); + void memcfg_w(offs_t offset, u32 data); + required_device m_maincpu; required_device m_eeprom; + required_ioport m_simms; + devcb_write_line m_int_dma_done_cb; devcb_read_line m_eisa_present; @@ -84,7 +88,7 @@ private: uint32_t m_gio64_arb_param; uint32_t m_arb_cpu_time; uint32_t m_arb_burst_time; - uint32_t m_mem_config[2]; + uint32_t m_memcfg[2]; uint32_t m_cpu_mem_access_config; uint32_t m_gio_mem_access_config; uint32_t m_cpu_error_addr; @@ -110,9 +114,10 @@ private: uint32_t m_dma_run; uint32_t m_eeprom_ctrl; uint32_t m_semaphore[16]; + + std::unique_ptr m_ram[4]; }; DECLARE_DEVICE_TYPE(SGI_MC, sgi_mc_device) - #endif // MAME_SGI_MC_H -- cgit v1.2.3