mirror of
https://github.com/holub/mame
synced 2025-10-05 08:41:31 +03:00
Added skeleton for Galileo System Controller
This commit is contained in:
parent
58e9a97e25
commit
5933e0d3da
600
src/devices/machine/gt64xxx.cpp
Normal file
600
src/devices/machine/gt64xxx.cpp
Normal 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), >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;
|
||||
}
|
259
src/devices/machine/gt64xxx.h
Normal file
259
src/devices/machine/gt64xxx.h
Normal 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
|
Loading…
Reference in New Issue
Block a user