From 5933e0d3dad67bc03d84f0b7e0be90a3612e3fcc Mon Sep 17 00:00:00 2001 From: Ted Green Date: Fri, 18 Mar 2016 15:04:00 -0600 Subject: [PATCH] Added skeleton for Galileo System Controller --- src/devices/machine/gt64xxx.cpp | 600 ++++++++++++++++++++++++++++++++ src/devices/machine/gt64xxx.h | 259 ++++++++++++++ 2 files changed, 859 insertions(+) create mode 100644 src/devices/machine/gt64xxx.cpp create mode 100644 src/devices/machine/gt64xxx.h diff --git a/src/devices/machine/gt64xxx.cpp b/src/devices/machine/gt64xxx.cpp new file mode 100644 index 00000000000..1b4f0a642ef --- /dev/null +++ b/src/devices/machine/gt64xxx.cpp @@ -0,0 +1,600 @@ +// license:BSD-3-Clause +// copyright-holders: Aaron Giles, Ted Green +#include "gt64xxx.h" + +/************************************* + * + * Debugging constants + * + *************************************/ +#define LOG_GALILEO (0) +#define LOG_REG (0) +#define LOG_TIMERS (0) +#define LOG_DMA (0) + +const device_type GT64XXX = &device_creator; + +DEVICE_ADDRESS_MAP_START(config_map, 32, gt64xxx_device) + AM_INHERIT_FROM(pci_device::config_map) +ADDRESS_MAP_END + +// cpu i/f map +DEVICE_ADDRESS_MAP_START(cpu_map, 32, gt64xxx_device) + AM_RANGE(0x00000000, 0x00000cff) AM_READWRITE( cpu_if_r, cpu_if_w) +ADDRESS_MAP_END + +gt64xxx_device::gt64xxx_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : pci_host_device(mconfig, GT64XXX, "Galileo GT-64XXX System Controller", tag, owner, clock, "gt64xxx", __FILE__), + m_be(0), m_autoconfig(0), m_irq_num(-1), + m_mem_config("memory_space", ENDIANNESS_LITTLE, 32, 32), + m_io_config("io_space", ENDIANNESS_LITTLE, 32, 32) +{ +} + +const address_space_config *gt64xxx_device::memory_space_config(address_spacenum spacenum) const +{ + return (spacenum == AS_PROGRAM) ? pci_bridge_device::memory_space_config(spacenum) : (spacenum == AS_DATA) ? &m_mem_config : (spacenum == AS_IO) ? &m_io_config : NULL; +} + +void gt64xxx_device::device_start() +{ + pci_host_device::device_start(); + m_cpu = machine().device(cpu_tag); + m_cpu_space = &m_cpu->space(AS_PROGRAM); + memory_space = &space(AS_DATA); + io_space = &space(AS_IO); + + memory_window_start = 0; + memory_window_end = 0xffffffff; + memory_offset = 0; + io_window_start = 0; + io_window_end = 0xffffffff; + io_offset = 0x00000000; + status = 0x0; + + // ROM size = 4 MB + m_cpu_space->install_rom (0x1fc00000, 0x1fffffff, m_region->base()); + + // MIPS drc + m_cpu->add_fastram(0x1fc00000, 0x1fffffff, TRUE, m_region->base()); +} + +void gt64xxx_device::device_reset() +{ + pci_device::device_reset(); + + // Configuration register defaults + m_reg[GREG_CPU_CONFIG] = m_be ? 0 : (1<<12); + m_reg[GREG_RAS_1_0_LO] = 0x0; + m_reg[GREG_RAS_1_0_HI] = 0x7; + m_reg[GREG_RAS_3_2_LO] = 0x8; + m_reg[GREG_RAS_3_2_HI] = 0xf; + m_reg[GREG_CS_2_0_LO] = 0xe0; + m_reg[GREG_CS_2_0_HI] = 0x70; + m_reg[GREG_CS_3_BOOT_LO] = 0xf8; + m_reg[GREG_CS_3_BOOT_HI] = 0x7f; + m_reg[GREG_PCI_IO_LO] = 0x80; + m_reg[GREG_PCI_IO_HI] = 0xf; + m_reg[GREG_PCI_MEM0_LO] = 0x90; + m_reg[GREG_PCI_MEM0_HI] = 0x1f; + m_reg[GREG_INTERNAL_SPACE] = 0xa0; + m_reg[GREG_PCI_MEM1_LO] = 0x790; + m_reg[GREG_PCI_MEM1_HI] = 0x1f; + + m_reg[GREG_RAS0_LO] = 0x0; + m_reg[GREG_RAS0_HI] = 0x7; + m_reg[GREG_RAS1_LO] = 0x8; + m_reg[GREG_RAS1_HI] = 0xf; + m_reg[GREG_RAS2_LO] = 0x10; + m_reg[GREG_RAS2_HI] = 0x17; + m_reg[GREG_RAS3_LO] = 0x18; + m_reg[GREG_RAS3_HI] = 0x1f; + m_reg[GREG_CS0_LO] = 0xc0; + m_reg[GREG_CS0_HI] = 0xc7; + m_reg[GREG_CS1_LO] = 0xc8; + m_reg[GREG_CS1_HI] = 0xcf; + m_reg[GREG_CS2_LO] = 0xd0; + m_reg[GREG_CS2_HI] = 0xdf; + m_reg[GREG_CS3_LO] = 0xf0; + m_reg[GREG_CS3_HI] = 0xfb; + m_reg[GREG_CSBOOT_LO] = 0xfc; + m_reg[GREG_CSBOOT_HI] = 0xff; + + m_reg[GREG_PCI_COMMAND] = m_be ? 0 : 1; + + map_cpu_space(); + regenerate_config_mapping(); +} + +void gt64xxx_device::map_cpu_space() +{ + UINT32 winStart, winEnd; + + // ROM region starts at 0x1fc00000 + m_cpu_space->unmap_readwrite(0x00000000, 0x1fbfffff); + m_cpu_space->unmap_readwrite(0x20000000, 0xffffffff); + + // Clear fastram regions in cpu after rom + m_cpu->clear_fastram(1); + + // CPU Regs + winStart = m_reg[GREG_INTERNAL_SPACE]<<21; + winEnd = winStart + sizeof(m_reg) - 1; + m_cpu_space->install_device(winStart, winEnd, *static_cast(this), >64xxx_device::cpu_map); + if (LOG_GALILEO) + logerror("%s: map_cpu_space cpu_reg start: %08X end: %08X\n", tag(), winStart, winEnd); + + // Ras0 + winStart = (m_reg[GREG_RAS_1_0_LO]<<21) | (m_reg[GREG_RAS0_LO]<<20); + winEnd = (m_reg[GREG_RAS_1_0_LO]<<21) | (m_reg[GREG_RAS0_HI]<<20) | 0xfffff; + m_ram[0].resize((winEnd+1-winStart)/4); + m_cpu_space->install_ram(winStart, winEnd, &m_ram[0][0]); + m_cpu->add_fastram(winStart, m_ram[0].size()*sizeof(m_ram[0][0]), FALSE, &m_ram[0][0]); + if (LOG_GALILEO) + logerror("%s: map_cpu_space ras0 start: %08X end: %08X\n", tag(), winStart, winEnd); + + // PCI IO Window + winStart = m_reg[GREG_PCI_IO_LO]<<21; + winEnd = (m_reg[GREG_PCI_IO_LO]<<21) | (m_reg[GREG_PCI_IO_HI]<<21) | 0x1fffff; + m_cpu_space->install_read_handler(winStart, winEnd, 0, 0, read32_delegate(FUNC(gt64xxx_device::master_io_r), this)); + m_cpu_space->install_write_handler(winStart, winEnd, 0, 0, write32_delegate(FUNC(gt64xxx_device::master_io_w), this)); + if (LOG_GALILEO) + logerror("%s: map_cpu_space pci_io start: %08X end: %08X\n", tag(), winStart, winEnd); + + // PCI MEM0 Window + winStart = m_reg[GREG_PCI_MEM0_LO]<<21; + winEnd = (m_reg[GREG_PCI_MEM0_LO]<<21) | (m_reg[GREG_PCI_MEM0_HI]<<21) | 0x1fffff; + m_cpu_space->install_read_handler(winStart, winEnd, 0, 0, read32_delegate(FUNC(gt64xxx_device::master_mem0_r), this)); + m_cpu_space->install_write_handler(winStart, winEnd, 0, 0, write32_delegate(FUNC(gt64xxx_device::master_mem0_w), this)); + if (LOG_GALILEO) + logerror("%s: map_cpu_space pci_mem0 start: %08X end: %08X\n", tag(), winStart, winEnd); + + // PCI MEM1 Window + winStart = m_reg[GREG_PCI_MEM1_LO]<<21; + winEnd = (m_reg[GREG_PCI_MEM1_LO]<<21) | (m_reg[GREG_PCI_MEM1_HI]<<21) | 0x1fffff; + m_cpu_space->install_read_handler(winStart, winEnd, 0, 0, read32_delegate(FUNC(gt64xxx_device::master_mem1_r), this)); + m_cpu_space->install_write_handler(winStart, winEnd, 0, 0, write32_delegate(FUNC(gt64xxx_device::master_mem1_w), this)); + if (LOG_GALILEO) + logerror("%s: map_cpu_space pci_mem1 start: %08X end: %08X\n", tag(), winStart, winEnd); + +} + +void gt64xxx_device::map_extra(UINT64 memory_window_start, UINT64 memory_window_end, UINT64 memory_offset, address_space *memory_space, + UINT64 io_window_start, UINT64 io_window_end, UINT64 io_offset, address_space *io_space) +{ + /* + UINT32 winStart, winEnd, winSize; + + // PCI Target Window 1 + if (m_cpu_regs[NREG_PCITW1]&0x1000) { + winStart = m_cpu_regs[NREG_PCITW1]&0xffe00000; + winEnd = winStart | (~(0xf0000000 | (((m_cpu_regs[NREG_PCITW1]>>13)&0x7f)<<21))); + winSize = winEnd - winStart + 1; + memory_space->install_read_handler(winStart, winEnd, 0, 0, read32_delegate(FUNC(gt64xxx_device::target1_r), this)); + memory_space->install_write_handler(winStart, winEnd, 0, 0, write32_delegate(FUNC(gt64xxx_device::target1_w), this)); + if (LOG_GALILEO) + logerror("%s: map_extra Target Window 1 start=%08X end=%08X size=%08X laddr=%08X\n", tag(), winStart, winEnd, winSize, m_target1_laddr); + } + */ +} + +void gt64xxx_device::reset_all_mappings() +{ + pci_device::reset_all_mappings(); +} + +// PCI bus control +READ32_MEMBER (gt64xxx_device::pci_config_r) +{ + UINT32 result = 0; + if (LOG_GALILEO) + logerror("%06X:galileo pci_config_r from offset %02X = %08X & %08X\n", space.device().safe_pc(), offset*4, result, mem_mask); + return result; +} +WRITE32_MEMBER (gt64xxx_device::pci_config_w) +{ + if (LOG_GALILEO) + logerror("%06X:galileo pci_config_w to offset %02X = %08X & %08X\n", space.device().safe_pc(), offset*4, data, mem_mask); +} +// PCI Master Window 0 +READ32_MEMBER (gt64xxx_device::master_mem0_r) +{ + UINT32 result = this->space(AS_DATA).read_dword((m_reg[GREG_PCI_MEM0_LO]<<21) | (offset*4), mem_mask); + if (LOG_GALILEO) + logerror("%06X:galileo pci mem0 read from offset %08X = %08X & %08X\n", space.device().safe_pc(), (m_reg[GREG_PCI_MEM0_LO]<<21) | (offset*4), result, mem_mask); + return result; +} +WRITE32_MEMBER (gt64xxx_device::master_mem0_w) +{ + this->space(AS_DATA).write_dword((m_reg[GREG_PCI_MEM0_LO]<<21) | (offset*4), data, mem_mask); + if (LOG_GALILEO) + logerror("%06X:galileo pci mem0 write to offset %08X = %08X & %08X\n", space.device().safe_pc(), (m_reg[GREG_PCI_MEM0_LO]<<21) | (offset*4), data, mem_mask); +} + +// PCI Master Window 1 +READ32_MEMBER (gt64xxx_device::master_mem1_r) +{ + UINT32 result = this->space(AS_DATA).read_dword((m_reg[GREG_PCI_MEM1_LO]<<21) | (offset*4), mem_mask); + if (LOG_GALILEO) + logerror("%06X:galileo pci mem1 read from offset %08X = %08X & %08X\n", space.device().safe_pc(), (m_reg[GREG_PCI_MEM1_LO]<<21) | (offset*4), result, mem_mask); + return result; +} +WRITE32_MEMBER (gt64xxx_device::master_mem1_w) +{ + this->space(AS_DATA).write_dword((m_reg[GREG_PCI_MEM1_LO]<<21) | (offset*4), data, mem_mask); + if (LOG_GALILEO) + logerror("%06X:galileo pci mem1 write to offset %08X = %08X & %08X\n", space.device().safe_pc(), (m_reg[GREG_PCI_MEM1_LO]<<21) | (offset*4), data, mem_mask); +} + +// PCI Master IO +READ32_MEMBER (gt64xxx_device::master_io_r) +{ + UINT32 result = this->space(AS_IO).read_dword((m_reg[GREG_PCI_IO_LO]<<21) | (offset*4), mem_mask); + if (LOG_GALILEO) + logerror("%06X:galileo pci io read from offset %08X = %08X & %08X\n", space.device().safe_pc(), (m_reg[GREG_PCI_IO_LO]<<21) | (offset*4), result, mem_mask); + return result; +} +WRITE32_MEMBER (gt64xxx_device::master_io_w) +{ + this->space(AS_IO).write_dword((m_reg[GREG_PCI_IO_LO]<<21) | (offset*4), data, mem_mask); + if (LOG_GALILEO) + logerror("%06X:galileo pciio write to offset %08X = %08X & %08X\n", space.device().safe_pc(), (m_reg[GREG_PCI_IO_LO]<<21) | (offset*4), data, mem_mask); +} + + +// CPU I/F +READ32_MEMBER (gt64xxx_device::cpu_if_r) +{ + UINT32 result = m_reg[offset]; + + /* switch off the offset for special cases */ + switch (offset) + { + case GREG_TIMER0_COUNT: + case GREG_TIMER1_COUNT: + case GREG_TIMER2_COUNT: + case GREG_TIMER3_COUNT: + { + int which = offset % 4; + galileo_timer *timer = &m_timer[which]; + + result = timer->count; + if (timer->active) + { + UINT32 elapsed = (timer->timer->elapsed() * m_clock).as_double(); + result = (result > elapsed) ? (result - elapsed) : 0; + } + + /* eat some time for those which poll this register */ + space.device().execute().eat_cycles(100); + + if (LOG_TIMERS) + logerror("%08X:hires_timer_r = %08X\n", space.device().safe_pc(), result); + break; + } + + case GREG_PCI_COMMAND: + // code at 40188 loops until this returns non-zero in bit 0 + //result = 0x0001; + break; + + case GREG_CONFIG_DATA: + result = config_data_r(space, offset); + break; + + case GREG_CONFIG_ADDRESS: + result = config_address_r(space, offset); + break; + + case GREG_INT_STATE: + case GREG_INT_MASK: + case GREG_TIMER_CONTROL: +// if (LOG_GALILEO) +// logerror("%08X:Galileo read from offset %03X = %08X\n", space.device().safe_pc(), offset*4, result); + break; + + default: + logerror("%08X:Galileo read from offset %03X = %08X\n", space.device().safe_pc(), offset*4, result); + break; + } + + if (m_be) result = FLIPENDIAN_INT32(result); + + return result; +} + +WRITE32_MEMBER(gt64xxx_device::cpu_if_w) +{ + if (m_be) { + data = FLIPENDIAN_INT32(data); + mem_mask = FLIPENDIAN_INT32(mem_mask); + } + + UINT32 oldata = m_reg[offset]; + COMBINE_DATA(&m_reg[offset]); + + /* switch off the offset for special cases */ + switch (offset) + { + case GREG_RAS_1_0_LO: + case GREG_RAS_1_0_HI: + case GREG_RAS_3_2_LO: + case GREG_RAS_3_2_HI: + case GREG_CS_2_0_LO: + case GREG_CS_2_0_HI: + case GREG_CS_3_BOOT_LO: + case GREG_CS_3_BOOT_HI: + case GREG_PCI_IO_LO: + case GREG_PCI_IO_HI: + case GREG_PCI_MEM0_LO: + case GREG_PCI_MEM0_HI: + case GREG_INTERNAL_SPACE: + case GREG_PCI_MEM1_LO: + case GREG_PCI_MEM1_HI: + map_cpu_space(); + if (LOG_GALILEO) + logerror("%08X:Galileo Memory Map data write to offset %03X = %08X & %08X\n", space.device().safe_pc(), offset*4, data, mem_mask); + break; + + case GREG_DMA0_CONTROL: + case GREG_DMA1_CONTROL: + case GREG_DMA2_CONTROL: + case GREG_DMA3_CONTROL: + { + int which = offset % 4; + + if (LOG_DMA) + logerror("%08X:Galileo write to offset %03X = %08X & %08X\n", space.device().safe_pc(), offset*4, data, mem_mask); + + /* keep the read only activity bit */ + m_reg[offset] &= ~0x4000; + m_reg[offset] |= (oldata & 0x4000); + + /* fetch next record */ + if (data & 0x2000) + dma_fetch_next(space, which); + m_reg[offset] &= ~0x2000; + + /* if enabling, start the DMA */ + if (!(oldata & 0x1000) && (data & 0x1000)) + perform_dma(space, which); + break; + } + + case GREG_TIMER0_COUNT: + case GREG_TIMER1_COUNT: + case GREG_TIMER2_COUNT: + case GREG_TIMER3_COUNT: + { + int which = offset % 4; + galileo_timer *timer = &m_timer[which]; + + if (which != 0) + data &= 0xffffff; + if (!timer->active) + timer->count = data; + if (LOG_TIMERS) + logerror("%08X:timer/counter %d count = %08X [start=%08X]\n", space.device().safe_pc(), offset % 4, data, timer->count); + break; + } + + case GREG_TIMER_CONTROL: + { + int which, mask; + + if (LOG_TIMERS) + logerror("%08X:timer/counter control = %08X\n", space.device().safe_pc(), data); + for (which = 0, mask = 0x01; which < 4; which++, mask <<= 2) + { + galileo_timer *timer = &m_timer[which]; + if (!timer->active && (data & mask)) + { + timer->active = 1; + if (timer->count == 0) + { + timer->count = m_reg[GREG_TIMER0_COUNT + which]; + if (which != 0) + timer->count &= 0xffffff; + } + timer->timer->adjust(TIMER_PERIOD * timer->count, which); + if (LOG_TIMERS) + logerror("Adjusted timer to fire in %f secs\n", (TIMER_PERIOD * timer->count).as_double()); + } + else if (timer->active && !(data & mask)) + { + UINT32 elapsed = (timer->timer->elapsed() * m_clock).as_double(); + timer->active = 0; + timer->count = (timer->count > elapsed) ? (timer->count - elapsed) : 0; + timer->timer->adjust(attotime::never, which); + if (LOG_TIMERS) + logerror("Disabled timer\n"); + } + } + break; + } + + case GREG_INT_STATE: + if (LOG_GALILEO) + logerror("%08X:Galileo write to IRQ clear = %08X & %08X\n", offset*4, data, mem_mask); + m_reg[offset] = oldata & data; + update_irqs(); + break; + + case GREG_CONFIG_DATA: + pci_host_device::config_data_w(space, offset, data); + if (LOG_GALILEO) + logerror("%08X:Galileo PCI config data write to offset %03X = %08X & %08X\n", space.device().safe_pc(), offset*4, data, mem_mask); + break; + + case GREG_CONFIG_ADDRESS: + pci_host_device::config_address_w(space, offset, data); + if (LOG_GALILEO) + logerror("%08X:Galileo PCI config address write to offset %03X = %08X & %08X\n", space.device().safe_pc(), offset*4, data, mem_mask); + break; + + case GREG_DMA0_COUNT: case GREG_DMA1_COUNT: case GREG_DMA2_COUNT: case GREG_DMA3_COUNT: + case GREG_DMA0_SOURCE: case GREG_DMA1_SOURCE: case GREG_DMA2_SOURCE: case GREG_DMA3_SOURCE: + case GREG_DMA0_DEST: case GREG_DMA1_DEST: case GREG_DMA2_DEST: case GREG_DMA3_DEST: + case GREG_DMA0_NEXT: case GREG_DMA1_NEXT: case GREG_DMA2_NEXT: case GREG_DMA3_NEXT: + case GREG_INT_MASK: + if (LOG_GALILEO) + logerror("%08X:Galileo write to offset %03X = %08X & %08X\n", space.device().safe_pc(), offset*4, data, mem_mask); + break; + + default: + logerror("%08X:Galileo write to offset %03X = %08X & %08X\n", space.device().safe_pc(), offset*4, data, mem_mask); + break; + } +} + +/************************************* + * + * Galileo timers & interrupts + * + *************************************/ + +void gt64xxx_device::update_irqs() +{ + int state = CLEAR_LINE; + + /* if any unmasked interrupts are live, we generate */ + if (m_reg[GREG_INT_STATE] & m_reg[GREG_INT_MASK]) + state = ASSERT_LINE; + if (m_irq_num != -1) + m_cpu->set_input_line(m_irq_num, state); + + if (LOG_GALILEO) + logerror("Galileo IRQ %s\n", (state == ASSERT_LINE) ? "asserted" : "cleared"); +} + + +TIMER_CALLBACK_MEMBER(gt64xxx_device::timer_callback) +{ + int which = param; + galileo_timer *timer = &m_timer[which]; + + if (LOG_TIMERS) + logerror("timer %d fired\n", which); + + /* copy the start value from the registers */ + timer->count = m_reg[GREG_TIMER0_COUNT + which]; + if (which != 0) + timer->count &= 0xffffff; + + /* if we're a timer, adjust the timer to fire again */ + if (m_reg[GREG_TIMER_CONTROL] & (2 << (2 * which))) + timer->timer->adjust(TIMER_PERIOD * timer->count, which); + else + timer->active = timer->count = 0; + + /* trigger the interrupt */ + m_reg[GREG_INT_STATE] |= 1 << (GINT_T0EXP_SHIFT + which); + update_irqs(); +} + +/************************************* + * + * Galileo DMA handler + * + *************************************/ + +int gt64xxx_device::dma_fetch_next(address_space &space, int which) +{ + offs_t address = 0; + UINT32 data; + + /* no-op for unchained mode */ + if (!(m_reg[GREG_DMA0_CONTROL + which] & 0x200)) + address = m_reg[GREG_DMA0_NEXT + which]; + + /* if we hit the end address, signal an interrupt */ + if (address == 0) + { + if (m_reg[GREG_DMA0_CONTROL + which] & 0x400) + { + m_reg[GREG_INT_STATE] |= 1 << (GINT_DMA0COMP_SHIFT + which); + update_irqs(); + } + m_reg[GREG_DMA0_CONTROL + which] &= ~0x5000; + return 0; + } + + /* fetch the byte count */ + data = space.read_dword(address); address += 4; + m_reg[GREG_DMA0_COUNT + which] = data; + + /* fetch the source address */ + data = space.read_dword(address); address += 4; + m_reg[GREG_DMA0_SOURCE + which] = data; + + /* fetch the dest address */ + data = space.read_dword(address); address += 4; + m_reg[GREG_DMA0_DEST + which] = data; + + /* fetch the next record address */ + data = space.read_dword(address); address += 4; + m_reg[GREG_DMA0_NEXT + which] = data; + return 1; +} + + +void gt64xxx_device::perform_dma(address_space &space, int which) +{ + do + { + offs_t srcaddr = m_reg[GREG_DMA0_SOURCE + which]; + offs_t dstaddr = m_reg[GREG_DMA0_DEST + which]; + UINT32 bytesleft = m_reg[GREG_DMA0_COUNT + which] & 0xffff; + int srcinc, dstinc; + + m_dma_active = which; + m_reg[GREG_DMA0_CONTROL + which] |= 0x5000; + + /* determine src/dst inc */ + switch ((m_reg[GREG_DMA0_CONTROL + which] >> 2) & 3) + { + default: + case 0: srcinc = 1; break; + case 1: srcinc = -1; break; + case 2: srcinc = 0; break; + } + switch ((m_reg[GREG_DMA0_CONTROL + which] >> 4) & 3) + { + default: + case 0: dstinc = 1; break; + case 1: dstinc = -1; break; + case 2: dstinc = 0; break; + } + + if (LOG_DMA) + logerror("Performing DMA%d: src=%08X dst=%08X bytes=%04X sinc=%d dinc=%d\n", which, srcaddr, dstaddr, bytesleft, srcinc, dstinc); + + /* standard transfer */ + while (bytesleft > 0) + { + space.write_byte(dstaddr, space.read_byte(srcaddr)); + srcaddr += srcinc; + dstaddr += dstinc; + bytesleft--; + } + + /* not verified, but seems logical these should be updated byte the end */ + m_reg[GREG_DMA0_SOURCE + which] = srcaddr; + m_reg[GREG_DMA0_DEST + which] = dstaddr; + m_reg[GREG_DMA0_COUNT + which] = (m_reg[GREG_DMA0_COUNT + which] & ~0xffff) | bytesleft; + m_dma_active = -1; + + /* if we did not hit zero, punt and return later */ + if (bytesleft != 0) + return; + + /* interrupt? */ + if (!(m_reg[GREG_DMA0_CONTROL + which] & 0x400)) + { + m_reg[GREG_INT_STATE] |= 1 << (GINT_DMA0COMP_SHIFT + which); + update_irqs(); + } + } while (dma_fetch_next(space, which)); + + m_reg[GREG_DMA0_CONTROL + which] &= ~0x5000; +} diff --git a/src/devices/machine/gt64xxx.h b/src/devices/machine/gt64xxx.h new file mode 100644 index 00000000000..be1539ab049 --- /dev/null +++ b/src/devices/machine/gt64xxx.h @@ -0,0 +1,259 @@ +// license:BSD-3-Clause +// copyright-holders: Aaron Giles, Ted Green +// Galileo GT-64xxx System Controller +// Skeleton code based off seattle machine driver. +// TODO: +// Testing +// Need PCI to be able to have a target delay a dma transfer +// Add PCI target maps +// Add PCI Func 1 calls +// Configurable byte swapping on cpu and pci busses. + +#ifndef GT64XXX_H +#define GT64XXX_H + +#include "pci.h" +#include "cpu/mips/mips3.h" + +// Supports R4600/4650/4700/R5000 CPUs +#define MCFG_GT64010_ADD(_tag, _cpu_tag, _clock) \ + MCFG_PCI_HOST_ADD(_tag, GT64XXX, 0x014611ab, 0x03, 0x00000000) \ + downcast(device)->set_cpu_tag(_cpu_tag); \ + downcast(device)->set_clock(_clock); + +// Supports the following 32-bit bus CPUs: +// IDT RC4640 and RC4650 (in 32-bit mode) +// QED RM523X +// NEC/Toshiba VR4300 +#define MCFG_GT64111_ADD(_tag, _cpu_tag, _clock) \ + MCFG_PCI_DEVICE_ADD(_tag, GT64XXX, 0x414611ab, 0x10, 0x058000, 0x00000000) \ + downcast(device)->set_cpu_tag(_cpu_tag); \ + downcast(device)->set_clock(_clock); + +#define MCFG_GT64XXX_SET_BE_CPU(_be) \ + downcast(device)->set_be(_be); + +#define MCFG_GT64XXX__IRQ_ADD(_irq_num) \ + downcast(device)->set_irq_info(_irq_num); + +/************************************* + * + * Galileo constants + * + *************************************/ + +//#define SYSTEM_CLOCK 50000000 +#define TIMER_PERIOD attotime::from_hz(m_clock) + +/* Galileo registers - 0x000-0x3ff */ +#define GREG_CPU_CONFIG (0x000/4) +#define GREG_RAS_1_0_LO (0x008/4) +#define GREG_RAS_1_0_HI (0x010/4) +#define GREG_RAS_3_2_LO (0x018/4) +#define GREG_RAS_3_2_HI (0x020/4) +#define GREG_CS_2_0_LO (0x028/4) +#define GREG_CS_2_0_HI (0x030/4) +#define GREG_CS_3_BOOT_LO (0x038/4) +#define GREG_CS_3_BOOT_HI (0x040/4) +#define GREG_PCI_IO_LO (0x048/4) +#define GREG_PCI_IO_HI (0x050/4) +#define GREG_PCI_MEM0_LO (0x058/4) +#define GREG_PCI_MEM0_HI (0x060/4) +#define GREG_INTERNAL_SPACE (0x068/4) +#define GREG_BUSERR_LO (0x070/4) +#define GREG_BUSERR_HI (0x078/4) +// GT-64111 only +#define GREG_PCI_MEM1_LO (0x080/4) +#define GREG_PCI_MEM1_HI (0x088/4) + +/* Galileo registers - 0x400-0x7ff */ +#define GREG_RAS0_LO (0x400/4) +#define GREG_RAS0_HI (0x404/4) +#define GREG_RAS1_LO (0x408/4) +#define GREG_RAS1_HI (0x40c/4) +#define GREG_RAS2_LO (0x410/4) +#define GREG_RAS2_HI (0x414/4) +#define GREG_RAS3_LO (0x418/4) +#define GREG_RAS3_HI (0x41c/4) +#define GREG_CS0_LO (0x420/4) +#define GREG_CS0_HI (0x424/4) +#define GREG_CS1_LO (0x428/4) +#define GREG_CS1_HI (0x42c/4) +#define GREG_CS2_LO (0x430/4) +#define GREG_CS2_HI (0x434/4) +#define GREG_CS3_LO (0x438/4) +#define GREG_CS3_HI (0x43c/4) +#define GREG_CSBOOT_LO (0x440/4) +#define GREG_CSBOOT_HI (0x444/4) +#define GREG_DRAM_CONFIG (0x448/4) +#define GREG_DRAM_BANK0 (0x44c/4) +#define GREG_DRAM_BANK1 (0x450/4) +#define GREG_DRAM_BANK2 (0x454/4) +#define GREG_DRAM_BANK3 (0x458/4) +#define GREG_DEVICE_BANK0 (0x45c/4) +#define GREG_DEVICE_BANK1 (0x460/4) +#define GREG_DEVICE_BANK2 (0x464/4) +#define GREG_DEVICE_BANK3 (0x468/4) +#define GREG_DEVICE_BOOT (0x46c/4) +#define GREG_ADDRESS_ERROR (0x470/4) + +/* Galileo registers - 0x800-0xbff */ +#define GREG_DMA0_COUNT (0x800/4) +#define GREG_DMA1_COUNT (0x804/4) +#define GREG_DMA2_COUNT (0x808/4) +#define GREG_DMA3_COUNT (0x80c/4) +#define GREG_DMA0_SOURCE (0x810/4) +#define GREG_DMA1_SOURCE (0x814/4) +#define GREG_DMA2_SOURCE (0x818/4) +#define GREG_DMA3_SOURCE (0x81c/4) +#define GREG_DMA0_DEST (0x820/4) +#define GREG_DMA1_DEST (0x824/4) +#define GREG_DMA2_DEST (0x828/4) +#define GREG_DMA3_DEST (0x82c/4) +#define GREG_DMA0_NEXT (0x830/4) +#define GREG_DMA1_NEXT (0x834/4) +#define GREG_DMA2_NEXT (0x838/4) +#define GREG_DMA3_NEXT (0x83c/4) +#define GREG_DMA0_CONTROL (0x840/4) +#define GREG_DMA1_CONTROL (0x844/4) +#define GREG_DMA2_CONTROL (0x848/4) +#define GREG_DMA3_CONTROL (0x84c/4) +#define GREG_TIMER0_COUNT (0x850/4) +#define GREG_TIMER1_COUNT (0x854/4) +#define GREG_TIMER2_COUNT (0x858/4) +#define GREG_TIMER3_COUNT (0x85c/4) +#define GREG_DMA_ARBITER (0x860/4) +#define GREG_TIMER_CONTROL (0x864/4) + +/* Galileo registers - 0xc00-0xfff */ +#define GREG_PCI_COMMAND (0xc00/4) +#define GREG_PCI_TIMEOUT (0xc04/4) +#define GREG_PCI_RAS_1_0 (0xc08/4) +#define GREG_PCI_RAS_3_2 (0xc0c/4) +#define GREG_PCI_CS_2_0 (0xc10/4) +#define GREG_PCI_CS_3_BOOT (0xc14/4) +#define GREG_INT_STATE (0xc18/4) +#define GREG_INT_MASK (0xc1c/4) +#define GREG_PCI_INT_MASK (0xc24/4) +#define GREG_CONFIG_ADDRESS (0xcf8/4) +#define GREG_CONFIG_DATA (0xcfc/4) + +/* Galileo interrupts */ +#define GINT_SUMMARY_SHIFT (0) +#define GINT_MEMOUT_SHIFT (1) +#define GINT_DMAOUT_SHIFT (2) +#define GINT_CPUOUT_SHIFT (3) +#define GINT_DMA0COMP_SHIFT (4) +#define GINT_DMA1COMP_SHIFT (5) +#define GINT_DMA2COMP_SHIFT (6) +#define GINT_DMA3COMP_SHIFT (7) +#define GINT_T0EXP_SHIFT (8) +#define GINT_T1EXP_SHIFT (9) +#define GINT_T2EXP_SHIFT (10) +#define GINT_T3EXP_SHIFT (11) +#define GINT_MASRDERR_SHIFT (12) +#define GINT_SLVWRERR_SHIFT (13) +#define GINT_MASWRERR_SHIFT (14) +#define GINT_SLVRDERR_SHIFT (15) +#define GINT_ADDRERR_SHIFT (16) +#define GINT_MEMERR_SHIFT (17) +#define GINT_MASABORT_SHIFT (18) +#define GINT_TARABORT_SHIFT (19) +#define GINT_RETRYCTR_SHIFT (20) + +/************************************* + * Structures + *************************************/ +struct galileo_timer +{ + emu_timer * timer; + UINT32 count; + UINT8 active; +}; + + +class gt64xxx_device : public pci_host_device { +public: + gt64xxx_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + virtual void reset_all_mappings(); + virtual void map_extra(UINT64 memory_window_start, UINT64 memory_window_end, UINT64 memory_offset, address_space *memory_space, + UINT64 io_window_start, UINT64 io_window_end, UINT64 io_offset, address_space *io_space); + + void set_cpu_tag(const char *tag) { cpu_tag = tag;} + void set_cpu_tag(const UINT32 clock) { m_clock = clock;} + void set_clock(const UINT32 clock) {m_clock = clock;} + void set_be(const int be) {m_be = be;} + void set_autoconfig(const int autoconfig) {m_autoconfig = autoconfig;} + void set_irq_info(const int irq_num) {m_irq_num = irq_num;} + + virtual DECLARE_ADDRESS_MAP(config_map, 32); + + // pci bus + DECLARE_READ32_MEMBER( pci_config_r); + DECLARE_WRITE32_MEMBER( pci_config_w); + + // cpu bus + DECLARE_READ32_MEMBER (cpu_if_r); + DECLARE_WRITE32_MEMBER(cpu_if_w); + + DECLARE_READ32_MEMBER (master_mem0_r); + DECLARE_WRITE32_MEMBER(master_mem0_w); + + DECLARE_READ32_MEMBER (master_mem1_r); + DECLARE_WRITE32_MEMBER(master_mem1_w); + + DECLARE_READ32_MEMBER (master_io_r); + DECLARE_WRITE32_MEMBER(master_io_w); + + // devices + DECLARE_READ32_MEMBER (ras_1_0_r); + DECLARE_WRITE32_MEMBER(ras_1_0_w); + DECLARE_READ32_MEMBER (ras_3_2_r); + DECLARE_WRITE32_MEMBER(ras_3_2_w); + DECLARE_READ32_MEMBER (cs_2_0_r); + DECLARE_WRITE32_MEMBER(cs_2_0_w); + DECLARE_READ32_MEMBER (cs_boot_3_r); + DECLARE_WRITE32_MEMBER(cs_boot_3_w); + +protected: + address_space *m_cpu_space; + virtual const address_space_config *memory_space_config(address_spacenum spacenum) const; + virtual void device_start(); + virtual void device_reset(); + +private: + mips3_device *m_cpu; + const char *cpu_tag; + UINT32 m_clock; + int m_be, m_autoconfig; + int m_irq_num; + + address_space_config m_mem_config, m_io_config; + + DECLARE_ADDRESS_MAP(cpu_map, 32); + + void map_cpu_space(); + + /* raw register data */ + UINT32 m_reg[0xd00/4]; + + /* timer info */ + galileo_timer m_timer[4]; + + /* DMA info */ + INT8 m_dma_active; + + // Ram + std::vector m_ram[4]; + + TIMER_CALLBACK_MEMBER(timer_callback); + void update_irqs(); + int dma_fetch_next(address_space &space, int which); + void perform_dma(address_space &space, int which); + +}; + +extern const device_type GT64XXX; + +#endif