Added skeleton for Galileo System Controller

This commit is contained in:
Ted Green 2016-03-18 15:04:00 -06:00
parent 58e9a97e25
commit 5933e0d3da
2 changed files with 859 additions and 0 deletions

View File

@ -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<gt64xxx_device>;
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<mips3_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<gt64xxx_device *>(this), &gt64xxx_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;
}

View File

@ -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<gt64xxx_device *>(device)->set_cpu_tag(_cpu_tag); \
downcast<gt64xxx_device *>(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<gt64xxx_device *>(device)->set_cpu_tag(_cpu_tag); \
downcast<gt64xxx_device *>(device)->set_clock(_clock);
#define MCFG_GT64XXX_SET_BE_CPU(_be) \
downcast<gt64xxx_device *>(device)->set_be(_be);
#define MCFG_GT64XXX__IRQ_ADD(_irq_num) \
downcast<gt64xxx_device *>(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<UINT32> 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