summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/mpc106.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/machine/mpc106.cpp')
-rw-r--r--src/devices/machine/mpc106.cpp384
1 files changed, 384 insertions, 0 deletions
diff --git a/src/devices/machine/mpc106.cpp b/src/devices/machine/mpc106.cpp
new file mode 100644
index 00000000000..3bc89e6174d
--- /dev/null
+++ b/src/devices/machine/mpc106.cpp
@@ -0,0 +1,384 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/**********************************************************************
+
+ mpc106.cpp - Motorola MPC106 PCI host bridge, aka "Grackle".
+
+ Can support up to 4 PowerPC CPUs, up to 1 GiB of RAM, and 16 MiB of ROM
+
+**********************************************************************/
+#include "emu.h"
+#include "mpc106.h"
+
+#define LOG_RAM (1U << 1)
+
+#define VERBOSE (0)
+#include "logmacro.h"
+
+enum
+{
+ AS_PCI_MEM = 1,
+ AS_PCI_IO = 2
+};
+
+constexpr u32 PICR1_LE_MODE = 0x00000020; // Host CPU is little-endian if set, big-endian if clear
+
+DEFINE_DEVICE_TYPE(MPC106, mpc106_host_device, "mpc106", "Motorola MPC106 PCI Bridge/Memory Controller")
+
+void mpc106_host_device::config_map(address_map &map)
+{
+ pci_host_device::config_map(map);
+ map(0x70, 0x71).rw(FUNC(mpc106_host_device::pwrconfig1_r), FUNC(mpc106_host_device::pwrconfig1_w));
+ map(0x72, 0x72).rw(FUNC(mpc106_host_device::pwrconfig2_r), FUNC(mpc106_host_device::pwrconfig2_w));
+ map(0x80, 0x8f).rw(FUNC(mpc106_host_device::memory_start_r), FUNC(mpc106_host_device::memory_start_w));
+ map(0x90, 0x9f).rw(FUNC(mpc106_host_device::memory_end_r), FUNC(mpc106_host_device::memory_end_w));
+ map(0xa0, 0xa0).rw(FUNC(mpc106_host_device::memory_enable_r), FUNC(mpc106_host_device::memory_enable_w));
+ map(0xa8, 0xab).rw(FUNC(mpc106_host_device::picr1_r), FUNC(mpc106_host_device::picr1_w));
+}
+
+mpc106_host_device::mpc106_host_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : pci_host_device(mconfig, MPC106, tag, owner, clock)
+ , m_mem_config("memory_space", ENDIANNESS_LITTLE, 32, 32)
+ , m_io_config("io_space", ENDIANNESS_LITTLE, 32, 32)
+ , m_cpu(*this, finder_base::DUMMY_TAG)
+{
+ set_ids_host(0x10570002, 0x40, 0x000006);
+ m_memory_bank_enable = 0;
+ m_picr1 = 0;
+}
+
+void mpc106_host_device::set_ram_info(u8 *ram_ptr, int ram_size)
+{
+ m_ram = ram_ptr;
+ m_ram_size = ram_size;
+}
+
+void mpc106_host_device::set_rom_tag(const char *tag)
+{
+ m_rom_tag = tag;
+}
+
+void mpc106_host_device::set_map_type(map_type maptype)
+{
+ m_map_type = maptype;
+}
+
+void mpc106_host_device::device_start()
+{
+ pci_host_device::device_start();
+ m_cpu_space = &m_cpu->space(AS_PCI_CONFIG);
+ set_spaces(&space(AS_PCI_MEM), &space(AS_PCI_IO));
+
+ memory_window_start = 0;
+ memory_window_end = 0xffffffff;
+ memory_offset = 0;
+ io_window_start = 0;
+ io_window_end = 0xffffffff;
+ io_offset = 0;
+ command = 0x0006;
+ status = 0x0080;
+ revision = 0x40;
+
+ m_rom = device().machine().root_device().memregion(m_rom_tag)->base();
+ m_rom_size = device().machine().root_device().memregion(m_rom_tag)->bytes();
+
+ m_pwrconfig1 = m_pwrconfig2 = 0;
+
+ u64 rom_base = 0x100000000ULL - m_rom_size;
+ m_cpu_space->install_rom(rom_base, 0xffffffff, m_rom);
+
+ if (m_map_type == MAP_TYPE_A)
+ { // type A is PReP
+ m_cpu_space->install_read_handler (0x80000000, 0x807fffff, read32s_delegate(*this, FUNC(mpc106_host_device::pci_io_r<0>)));
+ m_cpu_space->install_write_handler(0x80000000, 0x807fffff, write32s_delegate(*this, FUNC(mpc106_host_device::pci_io_w<0>)));
+
+ m_cpu_space->install_device(0x80000000, 0x80000cff, *static_cast<pci_host_device *>(this), &pci_host_device::io_configuration_access_map);
+
+ m_cpu_space->install_read_handler (0x81000000, 0xbf7fffff, read32s_delegate(*this, FUNC(mpc106_host_device::pci_io_r<0x01000000>)));
+ m_cpu_space->install_write_handler(0x81000000, 0xbf7fffff, write32s_delegate(*this, FUNC(mpc106_host_device::pci_io_w<0x01000000>)));
+ m_cpu_space->install_read_handler (0xc0000000, 0xfeffffff, read32s_delegate(*this, FUNC(mpc106_host_device::pci_memory_r<0>)));
+ m_cpu_space->install_write_handler(0xc0000000, 0xfeffffff, write32s_delegate(*this, FUNC(mpc106_host_device::pci_memory_w<0>)));
+ }
+ else if (m_map_type == MAP_TYPE_B)
+ { // type B is CHRP
+ m_cpu_space->install_read_handler (0x80000000, 0xfcffffff, read32s_delegate(*this, FUNC(mpc106_host_device::pci_memory_r<0x80000000>)));
+ m_cpu_space->install_write_handler(0x80000000, 0xfcffffff, write32s_delegate(*this, FUNC(mpc106_host_device::pci_memory_w<0x80000000>)));
+ m_cpu_space->install_read_handler (0xfd000000, 0xfdffffff, read32s_delegate(*this, FUNC(mpc106_host_device::pci_memory_r<0>)));
+ m_cpu_space->install_write_handler(0xfd000000, 0xfdffffff, write32s_delegate(*this, FUNC(mpc106_host_device::pci_memory_w<0>)));
+ m_cpu_space->install_read_handler (0xfe000000, 0xfe00ffff, read32s_delegate(*this, FUNC(mpc106_host_device::pci_io_r<0>)));
+ m_cpu_space->install_write_handler(0xfe000000, 0xfe00ffff, write32s_delegate(*this, FUNC(mpc106_host_device::pci_io_w<0>)));
+ m_cpu_space->install_read_handler (0xfe800000, 0xfebfffff, read32s_delegate(*this, FUNC(mpc106_host_device::pci_io_r<0x00800000>)));
+ m_cpu_space->install_write_handler(0xfe800000, 0xfebfffff, write32s_delegate(*this, FUNC(mpc106_host_device::pci_io_w<0x00800000>)));
+
+ if (m_picr1 & PICR1_LE_MODE)
+ {
+ m_cpu_space->install_device(0xfec00000, 0xfeefffff, *static_cast<mpc106_host_device *>(this), &mpc106_host_device::access_map_le);
+ }
+ else
+ {
+ m_cpu_space->install_device(0xfec00000, 0xfeefffff, *static_cast<mpc106_host_device *>(this), &mpc106_host_device::access_map_be);
+ }
+ }
+
+ save_item(NAME(m_pwrconfig1));
+ save_item(NAME(m_pwrconfig2));
+ save_item(NAME(m_memory_starts));
+ save_item(NAME(m_memory_ends));
+ save_item(NAME(m_memory_bank_enable));
+ save_item(NAME(m_picr1));
+}
+
+device_memory_interface::space_config_vector mpc106_host_device::memory_space_config() const
+{
+ auto r = pci_bridge_device::memory_space_config();
+ r.emplace_back(std::make_pair(AS_PCI_MEM, &m_mem_config));
+ r.emplace_back(std::make_pair(AS_PCI_IO, &m_io_config));
+ return r;
+}
+
+void mpc106_host_device::reset_all_mappings()
+{
+ pci_host_device::reset_all_mappings();
+}
+
+void mpc106_host_device::device_reset()
+{
+ pci_host_device::device_reset();
+}
+
+void mpc106_host_device::access_map_le(address_map &map)
+{
+ map(0x00000000, 0x001fffff).rw(FUNC(mpc106_host_device::config_address_r), FUNC(mpc106_host_device::config_address_w));
+ map(0x00200000, 0x002fffff).rw(FUNC(mpc106_host_device::config_data_r), FUNC(mpc106_host_device::config_data_w));
+}
+
+void mpc106_host_device::access_map_be(address_map &map)
+{
+ map(0x00000000, 0x001fffff).rw(FUNC(mpc106_host_device::be_config_address_r), FUNC(mpc106_host_device::be_config_address_w));
+ map(0x00200000, 0x002fffff).rw(FUNC(mpc106_host_device::be_config_data_r), FUNC(mpc106_host_device::be_config_data_w));
+}
+
+u32 mpc106_host_device::be_config_address_r()
+{
+ return swapendian_int32(pci_host_device::config_address_r());
+}
+
+void mpc106_host_device::be_config_address_w(offs_t offset, u32 data, u32 mem_mask)
+{
+ pci_host_device::config_address_w(offset, swapendian_int32(data), swapendian_int32(mem_mask));
+}
+
+u32 mpc106_host_device::be_config_data_r(offs_t offset, u32 mem_mask)
+{
+ return swapendian_int32(pci_host_device::config_data_r(offset, swapendian_int32(mem_mask)));
+}
+
+void mpc106_host_device::be_config_data_w(offs_t offset, u32 data, u32 mem_mask)
+{
+ pci_host_device::config_data_w(offset, swapendian_int32(data), swapendian_int32(mem_mask));
+}
+
+template <u32 Base>
+u32 mpc106_host_device::cpu_memory_r(offs_t offset, u32 mem_mask)
+{
+ if (m_picr1 & PICR1_LE_MODE)
+ {
+ return m_cpu_space->read_dword(Base + (offset * 4), mem_mask);
+ }
+ else
+ {
+ return swapendian_int32(m_cpu_space->read_dword(Base + (offset * 4), swapendian_int32(mem_mask)));
+ }
+}
+
+template <u32 Base>
+void mpc106_host_device::cpu_memory_w(offs_t offset, u32 data, u32 mem_mask)
+{
+ if (m_picr1 & PICR1_LE_MODE)
+ {
+ m_cpu_space->write_dword(Base + (offset * 4), data, mem_mask);
+ }
+ else
+ {
+ m_cpu_space->write_dword(Base + (offset * 4), swapendian_int32(data), swapendian_int32(mem_mask));
+ }
+}
+
+template u32 mpc106_host_device::cpu_memory_r<0>(offs_t offset, u32 mem_mask);
+template u32 mpc106_host_device::cpu_memory_r<0xff800000>(offs_t offset, u32 mem_mask);
+
+template void mpc106_host_device::cpu_memory_w<0>(offs_t offset, u32 data, u32 mem_mask);
+template void mpc106_host_device::cpu_memory_w<0xff800000>(offs_t offset, u32 data, u32 mem_mask);
+
+template <u32 Base>
+u32 mpc106_host_device::pci_memory_r(offs_t offset, u32 mem_mask)
+{
+ if (m_picr1 & PICR1_LE_MODE)
+ {
+ return this->space(AS_PCI_MEM).read_dword(Base + (offset * 4), mem_mask);
+ }
+ else
+ {
+ return swapendian_int32(this->space(AS_PCI_MEM).read_dword(Base + (offset * 4), swapendian_int32(mem_mask)));
+ }
+}
+
+template <u32 Base>
+void mpc106_host_device::pci_memory_w(offs_t offset, u32 data, u32 mem_mask)
+{
+ if (m_picr1 & PICR1_LE_MODE)
+ {
+ this->space(AS_PCI_MEM).write_dword(Base + (offset * 4), data, mem_mask);
+ }
+ else
+ {
+ this->space(AS_PCI_MEM).write_dword(Base + (offset * 4), swapendian_int32(data), swapendian_int32((mem_mask)));
+ }
+}
+
+template u32 mpc106_host_device::pci_memory_r<0>(offs_t offset, u32 mem_mask);
+template u32 mpc106_host_device::pci_memory_r<0x80000000>(offs_t offset, u32 mem_mask);
+
+template void mpc106_host_device::pci_memory_w<0>(offs_t offset, u32 data, u32 mem_mask);
+template void mpc106_host_device::pci_memory_w<0x80000000>(offs_t offset, u32 data, u32 mem_mask);
+
+template <u32 Base>
+u32 mpc106_host_device::pci_io_r(offs_t offset, u32 mem_mask)
+{
+ if (m_picr1 & PICR1_LE_MODE)
+ {
+ return this->space(AS_PCI_IO).read_dword(Base + (offset * 4), mem_mask);
+ }
+ else
+ {
+ return swapendian_int32(this->space(AS_PCI_IO).read_dword(Base + (offset * 4), swapendian_int32(mem_mask)));
+ }
+}
+
+template <u32 Base>
+void mpc106_host_device::pci_io_w(offs_t offset, u32 data, u32 mem_mask)
+{
+ if (m_picr1 & PICR1_LE_MODE)
+ {
+ this->space(AS_PCI_IO).write_dword(Base + (offset * 4), data, mem_mask);
+ }
+ else
+ {
+ this->space(AS_PCI_IO).write_dword(Base + (offset * 4), swapendian_int32(data), swapendian_int32((mem_mask)));
+ }
+}
+
+template u32 mpc106_host_device::pci_io_r<0>(offs_t offset, u32 mem_mask);
+template u32 mpc106_host_device::pci_io_r<0x01000000>(offs_t offset, u32 mem_mask);
+template u32 mpc106_host_device::pci_io_r<0x00800000>(offs_t offset, u32 mem_mask);
+
+template void mpc106_host_device::pci_io_w<0>(offs_t offset, u32 data, u32 mem_mask);
+template void mpc106_host_device::pci_io_w<0x01000000>(offs_t offset, u32 data, u32 mem_mask);
+template void mpc106_host_device::pci_io_w<0x00800000>(offs_t offset, u32 data, u32 mem_mask);
+
+// map PCI memory and I/O space stuff here
+void mpc106_host_device::map_extra(u64 memory_window_start, u64 memory_window_end, u64 memory_offset, address_space *memory_space,
+ u64 io_window_start, u64 io_window_end, u64 io_offset, address_space *io_space)
+{
+ // map RAM and ROM into the PCI memory space (because the PPC bus is 64 bits wide, and weirdness happens on DMA otherwise)
+ memory_space->install_read_handler(0xff800000, 0xffffffff, read32s_delegate(*this, FUNC(mpc106_host_device::cpu_memory_r<0xff800000>)));
+
+ memory_space->install_read_handler(0, m_ram_size - 1, read32s_delegate(*this, FUNC(mpc106_host_device::cpu_memory_r<0>)));
+ memory_space->install_write_handler(0, m_ram_size - 1, write32s_delegate(*this, FUNC(mpc106_host_device::cpu_memory_w<0>)));
+}
+
+u16 mpc106_host_device::pwrconfig1_r()
+{
+ return m_pwrconfig1;
+}
+
+void mpc106_host_device::pwrconfig1_w(offs_t offset, u16 data, u16 mem_mask)
+{
+ COMBINE_DATA(&m_pwrconfig1);
+}
+
+u8 mpc106_host_device::pwrconfig2_r()
+{
+ return m_pwrconfig2;
+}
+
+void mpc106_host_device::pwrconfig2_w(offs_t offset, u8 data)
+{
+ m_pwrconfig2 = data;
+}
+
+u32 mpc106_host_device::memory_start_r(offs_t offset)
+{
+ return m_memory_starts[offset];
+}
+
+void mpc106_host_device::memory_start_w(offs_t offset, u32 data, u32 mem_mask)
+{
+ COMBINE_DATA(&m_memory_starts[offset]);
+ LOGMASKED(LOG_RAM, "%s: %08x to memory start @ %x\n", tag(), data, offset);
+}
+
+u32 mpc106_host_device::memory_end_r(offs_t offset)
+{
+ return m_memory_ends[offset];
+}
+
+void mpc106_host_device::memory_end_w(offs_t offset, u32 data, u32 mem_mask)
+{
+ COMBINE_DATA(&m_memory_ends[offset]);
+ LOGMASKED(LOG_RAM, "%s: %08x to memory end @ %x\n", tag(), data, offset);
+}
+
+u8 mpc106_host_device::memory_enable_r()
+{
+ return m_memory_bank_enable;
+}
+
+void mpc106_host_device::memory_enable_w(offs_t offset, u8 data)
+{
+ LOGMASKED(LOG_RAM, "%s: %02x to memory_enable\n", tag(), data);
+ m_memory_bank_enable = data;
+
+ // unmap all RAM
+ m_cpu_space->unmap_readwrite(0x00000000, 0x0fffffff);
+
+ u64 base = m_memory_starts[0] | ((u64)m_memory_starts[1] << 32);
+ u64 base2 = m_memory_starts[2] | ((u64)m_memory_starts[3] << 32);
+ u64 end = m_memory_ends[0] | ((u64)m_memory_ends[0] << 32);
+ u64 end2 = m_memory_ends[2] | ((u64)m_memory_ends[3] << 32);
+ u32 bank_start = 0;
+ u32 bank_end = 0;
+ u64 install_ptr = 0;
+
+ for (int bank = 0; bank < 8; bank++)
+ {
+ if (((base & 0xff) != 0xff) && (BIT(m_memory_bank_enable, bank)))
+ {
+ bank_start = (base & 0xff) << 20;
+ bank_start |= (base2 & 0xff) << 28;
+ bank_end = (end & 0xff) << 20;
+ bank_end |= (end2 & 0xff) << 28;
+ bank_end |= 0xfffff;
+
+ LOGMASKED(LOG_RAM, "bank %d: start %08x end %08x, install_ptr = %llx\n", bank, bank_start, bank_end, install_ptr);
+
+ m_cpu_space->install_ram(bank_start, bank_end, &m_ram[install_ptr]);
+ install_ptr += (bank_end + 1);
+ }
+
+ base >>= 8;
+ base2 >>= 8;
+ end >>= 8;
+ end2 >>= 8;
+ }
+}
+
+u32 mpc106_host_device::picr1_r()
+{
+ return m_picr1;
+}
+
+void mpc106_host_device::picr1_w(u32 data)
+{
+ m_picr1 = data;
+}