(nw) Merge branch 'seattle_pci'

This commit is contained in:
Ted Green 2016-05-17 11:17:57 -06:00
commit a8b214c9aa
6 changed files with 632 additions and 93 deletions

View File

@ -1737,6 +1737,8 @@ if (MACHINES["PCI"]~=null) then
MAME_DIR .. "src/devices/machine/pci-usb.h",
MAME_DIR .. "src/devices/machine/pci-sata.cpp",
MAME_DIR .. "src/devices/machine/pci-sata.h",
MAME_DIR .. "src/devices/machine/pci-ide.cpp",
MAME_DIR .. "src/devices/machine/pci-ide.h",
MAME_DIR .. "src/devices/machine/pci-apic.cpp",
MAME_DIR .. "src/devices/machine/pci-apic.h",
MAME_DIR .. "src/devices/machine/pci-smbus.cpp",

View File

@ -8,9 +8,9 @@
*
*************************************/
#define LOG_GALILEO (0)
#define LOG_REG (0)
#define LOG_TIMERS (0)
#define LOG_DMA (0)
#define LOG_PCI (0)
const device_type GT64XXX = &device_creator<gt64xxx_device>;
@ -28,10 +28,19 @@ gt64xxx_device::gt64xxx_device(const machine_config &mconfig, const char *tag, d
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),
m_region(*this, DEVICE_SELF)
m_romRegion(*this, "rom"),
m_updateRegion(*this, "update"), m_cs_map(4)
{
}
void gt64xxx_device::set_cs_map(int id, address_map_constructor map, const char *name, device_t *device)
{
m_cs_map[id].enable = true;
m_cs_map[id].name = name;
m_cs_map[id].device = device;
m_cs_map[id].map = map;
}
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 : nullptr;
@ -53,11 +62,35 @@ void gt64xxx_device::device_start()
io_offset = 0x00000000;
status = 0x0;
// ROM size = 4 MB
m_cpu_space->install_rom (0x1fc00000, 0x1fffffff, m_region->base());
//dma_addr_map.reserve(static_cast<size_t>(proc_addr_bank::ADDR_NUM));
dma_addr_map.resize(static_cast<size_t>(proc_addr_bank::ADDR_NUM));
// MIPS drc
m_cpu->add_fastram(0x1fc00000, 0x1fffffff, TRUE, m_region->base());
// DMA timer
m_dma_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(gt64xxx_device::perform_dma), this));
// Leave the timer disabled.
m_dma_timer->adjust(attotime::never, 0, DMA_TIMER_PERIOD);
// ROM
UINT32 romSize = m_romRegion->bytes();
m_cpu_space->install_rom (0x1fc00000, 0x1fc00000 + romSize - 1, m_romRegion->base());
// ROM MIPS DRC
m_cpu->add_fastram(0x1fc00000, 0x1fc00000 + romSize - 1, TRUE, m_romRegion->base());
if (LOG_GALILEO)
logerror("%s: gt64xxx_device::device_start ROM Mapped size: 0x%08X start: 0x1fc00000 end: %08X\n", tag(), romSize, 0x1fc00000 + romSize - 1);
// Update region address is based on seattle driver
if (m_updateRegion) {
romSize = m_updateRegion->bytes();
m_cpu_space->install_rom(0x1fd00000, 0x1fd00000 + romSize - 1, m_updateRegion->base());
if (LOG_GALILEO)
logerror("%s: gt64xxx_device::device_start UPDATE Mapped size: 0x%08X start: 0x1fd00000 end: %08X\n", tag(), romSize, 0x1fd00000 + romSize - 1);
}
/* allocate timers for the galileo */
m_timer[0].timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(gt64xxx_device::timer_callback), this));
m_timer[1].timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(gt64xxx_device::timer_callback), this));
m_timer[2].timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(gt64xxx_device::timer_callback), this));
m_timer[3].timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(gt64xxx_device::timer_callback), this));
}
void gt64xxx_device::device_reset()
@ -105,6 +138,12 @@ void gt64xxx_device::device_reset()
map_cpu_space();
regenerate_config_mapping();
m_dma_active = 0;
m_dma_timer->adjust(attotime::never);
m_last_dma = 0;
m_prev_addr = 0;
}
void gt64xxx_device::map_cpu_space()
@ -125,14 +164,40 @@ void gt64xxx_device::map_cpu_space()
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);
// RAS[0:3]
for (int ramIndex = 0; ramIndex < 4; ++ramIndex)
{
winStart = (m_reg[GREG_RAS_1_0_LO + 0x10 / 4 * (ramIndex/2)] << 21) | (m_reg[GREG_RAS0_LO + 0x8 / 4 * ramIndex] << 20);
winEnd = (m_reg[GREG_RAS_1_0_LO + 0x10 / 4 * (ramIndex / 2)] << 21) | (m_reg[GREG_RAS0_HI + 0x8 / 4 * ramIndex] << 20) | 0xfffff;
m_ram[ramIndex].resize((winEnd + 1 - winStart) / 4);
m_cpu_space->install_ram(winStart, winEnd, m_ram[ramIndex].data());
//m_cpu->add_fastram(winStart, m_ram[ramIndex].size() * sizeof(m_ram[ramIndex][0]), FALSE, &m_ram[ramIndex][0]);
//m_cpu->add_fastram(winStart, m_ram[ramIndex].size() * sizeof(UINT32), FALSE, m_ram[ramIndex].data());
if (LOG_GALILEO)
logerror("%s: map_cpu_space ras[%i] start: %08X end: %08X\n", tag(), ramIndex, winStart, winEnd);
}
// CS[0:3]
//m_cpu_space->install_device_delegate(0x16000000, 0x17ffffff, machine().root_device(), m_cs_map[3].map);
typedef void (gt64xxx_device::*tramp_t)(::address_map &, device_t &);
static const tramp_t trampolines[4] = {
&gt64xxx_device::map_trampoline<0>,
&gt64xxx_device::map_trampoline<1>,
&gt64xxx_device::map_trampoline<2>,
&gt64xxx_device::map_trampoline<3>
};
for (int ramIndex = 0; ramIndex < 4; ++ramIndex)
{
if (m_cs_map[ramIndex].enable)
{
winStart = (m_reg[GREG_CS_2_0_LO + 0x10 / 4 * (ramIndex / 3)] << 21) | (m_reg[GREG_CS0_LO + 0x8 / 4 * ramIndex] << 20);
winEnd = (m_reg[GREG_CS_2_0_LO + 0x10 / 4 * (ramIndex / 3)] << 21) | (m_reg[GREG_CS0_HI + 0x8 / 4 * ramIndex] << 20) | 0xfffff;
install_cs_map(winStart, winEnd, trampolines[ramIndex], m_cs_map[ramIndex].name);
if (LOG_GALILEO)
logerror("%s: map_cpu_space cs[%i] start: %08X end: %08X\n", tag(), ramIndex, winStart, winEnd);
}
}
// PCI IO Window
winStart = m_reg[GREG_PCI_IO_LO]<<21;
@ -158,25 +223,79 @@ void gt64xxx_device::map_cpu_space()
if (LOG_GALILEO)
logerror("%s: map_cpu_space pci_mem1 start: %08X end: %08X\n", tag(), winStart, winEnd);
// Setup the address mapping table for DMA lookups
for (size_t index = 0; index < proc_addr_bank::ADDR_NUM; ++index)
{
if (index < proc_addr_bank::ADDR_PCI_MEM1) {
dma_addr_map[index].low_addr = (m_reg[GREG_RAS_1_0_LO + 0x10 / 4 * index] << 21);
dma_addr_map[index].high_addr = (dma_addr_map[index].low_addr & 0xf0000000) | (m_reg[GREG_RAS_1_0_HI + 0x10 / 4 * index] << 21) | 0x1fffff;
}
else {
dma_addr_map[index].low_addr = (m_reg[GREG_PCI_MEM1_LO] << 21);
dma_addr_map[index].high_addr = (dma_addr_map[index].low_addr & 0xf0000000) | (m_reg[GREG_PCI_MEM1_HI] << 21) | 0x1fffff;
}
switch (index) {
case proc_addr_bank::ADDR_PCI_IO:
dma_addr_map[index].space = &this->space(AS_IO);
break;
case proc_addr_bank::ADDR_PCI_MEM0:
case proc_addr_bank::ADDR_PCI_MEM1:
dma_addr_map[index].space = &this->space(AS_DATA);
break;
default:
dma_addr_map[index].space = m_cpu_space;
break;
}
}
}
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)
{
/*
int ramIndex;
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);
}
*/
// Not sure if GREG_RAS_1_0_LO should be added on PCI address map side.
// RAS0
ramIndex = 0;
winStart = (m_reg[GREG_RAS_1_0_LO + 0x10 / 4 * (ramIndex / 2)] << 21) | (m_reg[GREG_RAS0_LO + 0x8 / 4 * ramIndex] << 20);
winEnd = (m_reg[GREG_RAS_1_0_LO + 0x10 / 4 * (ramIndex / 2)] << 21) | (m_reg[GREG_RAS0_HI + 0x8 / 4 * ramIndex] << 20) | 0xfffff;
winSize = winEnd - winStart + 1;
memory_space->install_read_handler(winStart, winEnd, 0, 0, read32_delegate(FUNC(gt64xxx_device::ras_0_r), this));
memory_space->install_write_handler(winStart, winEnd, 0, 0, write32_delegate(FUNC(gt64xxx_device::ras_0_w), this));
if (LOG_GALILEO)
logerror("%s: map_extra RAS0 start=%08X end=%08X size=%08X\n", tag(), winStart, winEnd, winSize);
// RAS1
ramIndex = 1;
winStart = (m_reg[GREG_RAS_1_0_LO + 0x10 / 4 * (ramIndex / 2)] << 21) | (m_reg[GREG_RAS0_LO + 0x8 / 4 * ramIndex] << 20);
winEnd = (m_reg[GREG_RAS_1_0_LO + 0x10 / 4 * (ramIndex / 2)] << 21) | (m_reg[GREG_RAS0_HI + 0x8 / 4 * ramIndex] << 20) | 0xfffff;
winSize = winEnd - winStart + 1;
memory_space->install_read_handler(winStart, winEnd, 0, 0, read32_delegate(FUNC(gt64xxx_device::ras_1_r), this));
memory_space->install_write_handler(winStart, winEnd, 0, 0, write32_delegate(FUNC(gt64xxx_device::ras_1_w), this));
if (LOG_GALILEO)
logerror("%s: map_extra RAS1 start=%08X end=%08X size=%08X\n", tag(), winStart, winEnd, winSize);
// RAS2
ramIndex = 2;
winStart = (m_reg[GREG_RAS_1_0_LO + 0x10 / 4 * (ramIndex / 2)] << 21) | (m_reg[GREG_RAS0_LO + 0x8 / 4 * ramIndex] << 20);
winEnd = (m_reg[GREG_RAS_1_0_LO + 0x10 / 4 * (ramIndex / 2)] << 21) | (m_reg[GREG_RAS0_HI + 0x8 / 4 * ramIndex] << 20) | 0xfffff;
winSize = winEnd - winStart + 1;
memory_space->install_read_handler(winStart, winEnd, 0, 0, read32_delegate(FUNC(gt64xxx_device::ras_2_r), this));
memory_space->install_write_handler(winStart, winEnd, 0, 0, write32_delegate(FUNC(gt64xxx_device::ras_2_w), this));
if (LOG_GALILEO)
logerror("%s: map_extra RAS2 start=%08X end=%08X size=%08X\n", tag(), winStart, winEnd, winSize);
// RAS3
ramIndex = 3;
winStart = (m_reg[GREG_RAS_1_0_LO + 0x10 / 4 * (ramIndex / 2)] << 21) | (m_reg[GREG_RAS0_LO + 0x8 / 4 * ramIndex] << 20);
winEnd = (m_reg[GREG_RAS_1_0_LO + 0x10 / 4 * (ramIndex / 2)] << 21) | (m_reg[GREG_RAS0_HI + 0x8 / 4 * ramIndex] << 20) | 0xfffff;
winSize = winEnd - winStart + 1;
memory_space->install_read_handler(winStart, winEnd, 0, 0, read32_delegate(FUNC(gt64xxx_device::ras_3_r), this));
memory_space->install_write_handler(winStart, winEnd, 0, 0, write32_delegate(FUNC(gt64xxx_device::ras_3_w), this));
if (LOG_GALILEO)
logerror("%s: map_extra RAS3 start=%08X end=%08X size=%08X\n", tag(), winStart, winEnd, winSize);
}
void gt64xxx_device::reset_all_mappings()
@ -201,14 +320,14 @@ WRITE32_MEMBER (gt64xxx_device::pci_config_w)
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)
if (LOG_PCI)
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)
if (LOG_PCI)
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);
}
@ -216,14 +335,14 @@ WRITE32_MEMBER (gt64xxx_device::master_mem0_w)
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)
if (LOG_PCI)
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)
if (LOG_PCI)
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);
}
@ -231,15 +350,79 @@ WRITE32_MEMBER (gt64xxx_device::master_mem1_w)
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);
if (LOG_PCI && m_prev_addr != offset) {
m_prev_addr = offset;
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);
if (LOG_PCI && m_prev_addr != offset) {
m_prev_addr = offset;
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);
}
}
READ32_MEMBER(gt64xxx_device::ras_0_r)
{
UINT32 result = m_ram[0][offset];
if (LOG_PCI)
logerror("%06X:galileo ras_0 read from offset %08X = %08X & %08X\n", space.device().safe_pc(), offset * 4, result, mem_mask);
return result;
}
WRITE32_MEMBER(gt64xxx_device::ras_0_w)
{
COMBINE_DATA(&m_ram[0][offset]);
if (LOG_PCI)
logerror("%06X:galileo ras_0 write to offset %08X = %08X & %08X\n", space.device().safe_pc(), offset * 4, data, mem_mask);
}
READ32_MEMBER(gt64xxx_device::ras_1_r)
{
UINT32 result = m_ram[1][offset];
if (LOG_PCI)
logerror("%06X:galileo ras_0 read from offset %08X = %08X & %08X\n", space.device().safe_pc(), offset * 4, result, mem_mask);
return result;
}
WRITE32_MEMBER(gt64xxx_device::ras_1_w)
{
COMBINE_DATA(&m_ram[1][offset]);
if (LOG_PCI)
logerror("%06X:galileo ras_0 write to offset %08X = %08X & %08X\n", space.device().safe_pc(), offset * 4, data, mem_mask);
}
READ32_MEMBER(gt64xxx_device::ras_2_r)
{
UINT32 result = m_ram[2][offset];
if (LOG_PCI)
logerror("%06X:galileo ras_0 read from offset %08X = %08X & %08X\n", space.device().safe_pc(), offset * 4, result, mem_mask);
return result;
}
WRITE32_MEMBER(gt64xxx_device::ras_2_w)
{
COMBINE_DATA(&m_ram[2][offset]);
if (LOG_PCI)
logerror("%06X:galileo ras_0 write to offset %08X = %08X & %08X\n", space.device().safe_pc(), offset * 4, data, mem_mask);
}
READ32_MEMBER(gt64xxx_device::ras_3_r)
{
UINT32 result = m_ram[3][offset];
if (LOG_PCI)
logerror("%06X:galileo ras_0 read from offset %08X = %08X & %08X\n", space.device().safe_pc(), offset * 4, result, mem_mask);
return result;
}
WRITE32_MEMBER(gt64xxx_device::ras_3_w)
{
COMBINE_DATA(&m_ram[3][offset]);
if (LOG_PCI)
logerror("%06X:galileo ras_0 write to offset %08X = %08X & %08X\n", space.device().safe_pc(), offset * 4, data, mem_mask);
}
@ -267,7 +450,7 @@ READ32_MEMBER (gt64xxx_device::cpu_if_r)
}
/* eat some time for those which poll this register */
space.device().execute().eat_cycles(100);
//space.device().execute().eat_cycles(100);
if (LOG_TIMERS)
logerror("%08X:hires_timer_r = %08X\n", space.device().safe_pc(), result);
@ -277,10 +460,15 @@ READ32_MEMBER (gt64xxx_device::cpu_if_r)
case GREG_PCI_COMMAND:
// code at 40188 loops until this returns non-zero in bit 0
//result = 0x0001;
// bit 0 => byte swap
// bit 2:1 => SyncMode, 00 = PCLK=[0,33], 01 = PCLK>=TClk/2, 10 = PCLK = TCLK/2
result = (result & ~0x1) | (m_be ^ 0x1);
break;
case GREG_CONFIG_DATA:
result = config_data_r(space, offset);
if (LOG_GALILEO)
logerror("%08X:Galileo GREG_CONFIG_DATA read from offset %03X = %08X\n", space.device().safe_pc(), offset*4, result);
break;
case GREG_CONFIG_ADDRESS:
@ -317,22 +505,24 @@ WRITE32_MEMBER(gt64xxx_device::cpu_if_w)
/* 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_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:
//case GREG_PCI_MEM1_LO:
//case GREG_PCI_MEM1_HI:
case GREG_CS3_HI:
map_cpu_space();
remap_cb();
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;
@ -344,9 +534,6 @@ WRITE32_MEMBER(gt64xxx_device::cpu_if_w)
{
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);
@ -357,8 +544,18 @@ WRITE32_MEMBER(gt64xxx_device::cpu_if_w)
m_reg[offset] &= ~0x2000;
/* if enabling, start the DMA */
if (!(oldata & 0x1000) && (data & 0x1000))
perform_dma(space, which);
if (!(oldata & 0x1000) && (data & 0x1000) && !(m_dma_active & (1<<which)))
{
// Trigger the timer if there are no dma's active
if (m_dma_active==0)
m_dma_timer->adjust(attotime::zero, 0, DMA_TIMER_PERIOD);
m_dma_active |= (1<< which);
//perform_dma(space, which);
if (LOG_DMA)
logerror("%08X:Galileo starting DMA Chan %i\n", space.device().safe_pc(), which);
}
if (LOG_GALILEO)
logerror("%08X:Galileo write to offset %03X = %08X & %08X\n", space.device().safe_pc(), offset * 4, data, mem_mask);
break;
}
@ -428,9 +625,30 @@ WRITE32_MEMBER(gt64xxx_device::cpu_if_w)
break;
case GREG_CONFIG_ADDRESS:
pci_host_device::config_address_w(space, offset, data);
// Type 0 config transactions signalled by Bus Num = 0 and Device Num != 0
// Bits 15:11 get mapped into device number for configuration
UINT32 modData;
if (0 && (data & 0xff0000) == 0x0 && (data & 0xf800)) {
// Type 0 transaction
modData = 0;
// Select the device based on one hot bit
for (int i = 11; i<16; i++) {
if ((data >> i) & 0x1) {
// One hot encoding, bit 11 will mean device 1
modData = i - 10;
break;
}
}
// Re-organize into Type 1 transaction for bus 0 (local bus)
modData = (modData << 11) | (data & 0x7ff) | (0x80000000);
}
else {
// Type 1 transaction, no modification needed
modData = data;
}
pci_host_device::config_address_w(space, offset, modData);
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);
logerror("%08X:Galileo PCI config address write to offset %03X = %08X & %08X origData = %08X\n", space.device().safe_pc(), offset*4, modData, mem_mask, data);
break;
case GREG_DMA0_COUNT: case GREG_DMA1_COUNT: case GREG_DMA2_COUNT: case GREG_DMA3_COUNT:
@ -464,8 +682,8 @@ void gt64xxx_device::update_irqs()
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");
if (1 && LOG_GALILEO)
logerror("Galileo IRQ %s irqNum: %i state = %08X mask = %08X\n", (state == ASSERT_LINE) ? "asserted" : "cleared", m_irq_num, m_reg[GREG_INT_STATE], m_reg[GREG_INT_MASK]);
}
@ -498,6 +716,15 @@ TIMER_CALLBACK_MEMBER(gt64xxx_device::timer_callback)
* Galileo DMA handler
*
*************************************/
address_space* gt64xxx_device::dma_decode_address(UINT32 &addr)
{
for (size_t index = 0; index < proc_addr_bank::ADDR_NUM; ++index)
{
if (addr >= dma_addr_map[index].low_addr && addr <= dma_addr_map[index].high_addr)
return dma_addr_map[index].space;
}
return nullptr;
}
int gt64xxx_device::dma_fetch_next(address_space &space, int which)
{
@ -539,16 +766,33 @@ int gt64xxx_device::dma_fetch_next(address_space &space, int which)
}
void gt64xxx_device::perform_dma(address_space &space, int which)
TIMER_CALLBACK_MEMBER (gt64xxx_device::perform_dma)
{
do
// Cycle through the channels
int which = -1;
for (int i = 1; i <= 4; i++)
{
which = (m_last_dma + i) % 4;
if ((m_dma_active & (1 << which)) && (m_reg[GREG_DMA0_CONTROL + which] & 0x1000))
break;
}
// Save which dma is processed for arbitration next time
m_last_dma = which;
if (which==-1)
{
logerror("gt64xxx_device::perform_dma Warning! DMA Timer called with no pending DMA. m_dma_active = %08X\n", m_dma_active);
} else
{
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;
address_space* srcSpace = dma_decode_address(srcaddr);
address_space* dstSpace = dma_decode_address(dstaddr);
int srcinc, dstinc;
m_dma_active = which;
m_reg[GREG_DMA0_CONTROL + which] |= 0x5000;
/* determine src/dst inc */
@ -570,32 +814,50 @@ void gt64xxx_device::perform_dma(address_space &space, int which)
if (LOG_DMA)
logerror("Performing DMA%d: src=%08X dst=%08X bytes=%04X sinc=%d dinc=%d\n", which, srcaddr, dstaddr, bytesleft, srcinc, dstinc);
int burstCount = 0;
/* standard transfer */
while (bytesleft > 0)
while (bytesleft > 0 && burstCount < DMA_BURST_SIZE)
{
if (bytesleft < 4)
{
space.write_byte(dstaddr, space.read_byte(srcaddr));
//space.write_byte(dstaddr, space.read_byte(srcaddr));
dstSpace->write_byte(dstaddr, srcSpace->read_byte(srcaddr));
srcaddr += srcinc;
dstaddr += dstinc;
bytesleft--;
}
else {
//space.write_byte(dstaddr, space.read_byte(srcaddr));
dstSpace->write_dword(dstaddr, srcSpace->read_dword(srcaddr));
srcaddr += srcinc * 4;
dstaddr += dstinc * 4;
bytesleft -= 4;
}
burstCount++;
}
/* 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;
// Fetch the next dma for this channel (to be performed next scheduled burst)
if (dma_fetch_next(*m_cpu_space, which) == 0)
{
m_dma_active &= ~(1 << which);
// Turn off the timer
m_dma_timer->adjust(attotime::never);
}
}
}

View File

@ -3,10 +3,7 @@
// 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
// Need PCI to be able to have a target delay (pci bus stall) a dma transfer
// Configurable byte swapping on cpu and pci busses.
#ifndef GT64XXX_H
@ -16,34 +13,42 @@
#include "cpu/mips/mips3.h"
// Supports R4600/4650/4700/R5000 CPUs
#define MCFG_GT64010_ADD(_tag, _cpu_tag, _clock) \
#define MCFG_GT64010_ADD(_tag, _cpu_tag, _clock, _irq_num) \
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);
downcast<gt64xxx_device *>(device)->set_clock(_clock); \
downcast<gt64xxx_device *>(device)->set_irq_num(_irq_num);
// 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) \
#define MCFG_GT64111_ADD(_tag, _cpu_tag, _clock, _irq_num) \
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);
downcast<gt64xxx_device *>(device)->set_clock(_clock); \
downcast<gt64xxx_device *>(device)->set_irq_num(_irq_num);
#define MCFG_GT64XXX_SET_BE_CPU(_be) \
downcast<gt64xxx_device *>(device)->set_be(_be);
#define MCFG_GT64XXX__IRQ_ADD(_irq_num) \
#define MCFG_GT64XXX_IRQ_ADD(_irq_num) \
downcast<gt64xxx_device *>(device)->set_irq_info(_irq_num);
#define MCFG_GT64XXX_SET_CS(_cs_num, _map) \
downcast<gt64xxx_device *>(device)->set_cs_map(_cs_num, ADDRESS_MAP_NAME(_map), #_map, owner);
/*************************************
*
* Galileo constants
*
*************************************/
//#define SYSTEM_CLOCK 50000000
#define TIMER_PERIOD attotime::from_hz(m_clock)
#define PCI_BUS_CLOCK 33000000
// Number of dma words to transfer at a time, real hardware configurable between 8-32
#define DMA_BURST_SIZE 32
#define DMA_TIMER_PERIOD attotime::from_hz(PCI_BUS_CLOCK / 48)
/* Galileo registers - 0x000-0x3ff */
#define GREG_CPU_CONFIG (0x000/4)
@ -161,6 +166,7 @@
#define GINT_TARABORT_SHIFT (19)
#define GINT_RETRYCTR_SHIFT (20)
/*************************************
* Structures
*************************************/
@ -171,6 +177,22 @@ struct galileo_timer
UINT8 active;
};
struct galileo_addr_map
{
UINT32 low_addr;
UINT32 high_addr;
address_space* space;
galileo_addr_map() : low_addr(0xffffffff), high_addr(0x0) {}
};
struct galileo_device_map
{
bool enable;
const char *name;
device_t *device;
address_map_constructor map;
galileo_device_map() : enable(false), device(nullptr) {}
};
class gt64xxx_device : public pci_host_device {
public:
@ -181,12 +203,10 @@ public:
UINT64 io_window_start, UINT64 io_window_end, UINT64 io_offset, address_space *io_space) override;
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;}
void set_irq_num(const int irq_num) {m_irq_num = irq_num;}
virtual DECLARE_ADDRESS_MAP(config_map, 32) override;
// pci bus
@ -207,14 +227,21 @@ public:
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);
DECLARE_READ32_MEMBER (ras_0_r);
DECLARE_WRITE32_MEMBER(ras_0_w);
DECLARE_READ32_MEMBER(ras_1_r);
DECLARE_WRITE32_MEMBER(ras_1_w);
DECLARE_READ32_MEMBER(ras_2_r);
DECLARE_WRITE32_MEMBER(ras_2_w);
DECLARE_READ32_MEMBER(ras_3_r);
DECLARE_WRITE32_MEMBER(ras_3_w);
DECLARE_READ32_MEMBER (cs_0_r);
DECLARE_WRITE32_MEMBER(cs_0_w);
// Enums
enum proc_addr_bank {ADDR_RAS1_0, ADDR_RAS3_2, ADDR_CS2_0, ADDR_CS3_BCS, ADDR_PCI_IO, ADDR_PCI_MEM0, ADDR_PCI_MEM1, ADDR_NUM};
void set_cs_map(int id, address_map_constructor map, const char *name, device_t *device);
protected:
address_space *m_cpu_space;
@ -222,6 +249,7 @@ protected:
virtual void device_start() override;
virtual void device_reset() override;
private:
mips3_device *m_cpu;
const char *cpu_tag;
@ -231,17 +259,20 @@ private:
address_space_config m_mem_config, m_io_config;
required_memory_region m_region;
required_memory_region m_romRegion;
optional_memory_region m_updateRegion;
DECLARE_ADDRESS_MAP(cpu_map, 32);
void map_cpu_space();
UINT32 m_prev_addr;
/* raw register data */
UINT32 m_reg[0xd00/4];
/* timer info */
galileo_timer m_timer[4];
TIMER_CALLBACK_MEMBER(timer_callback);
/* DMA info */
INT8 m_dma_active;
@ -249,10 +280,26 @@ private:
// Ram
std::vector<UINT32> m_ram[4];
TIMER_CALLBACK_MEMBER(timer_callback);
// Chip Select
std::vector<galileo_device_map> m_cs_map;
template<int id> void map_trampoline(::address_map &map, device_t &device) {
m_cs_map[id].map(map, *m_cs_map[id].device);
}
template <typename T> void install_cs_map(offs_t addrstart, offs_t addrend, void (T::*map)(::address_map &map, device_t &device), const char *name) {
//address_map_delegate delegate(map, name, static_cast<T *>(this));
address_map_delegate delegate(map, name, static_cast<T *>(this));
m_cpu_space->install_device_delegate(addrstart, addrend, *this, delegate);
}
void update_irqs();
int m_last_dma;
emu_timer* m_dma_timer;
std::vector<galileo_addr_map> dma_addr_map;
int dma_fetch_next(address_space &space, int which);
void perform_dma(address_space &space, int which);
TIMER_CALLBACK_MEMBER(perform_dma);
address_space* dma_decode_address(UINT32 &addr);
};

View File

@ -0,0 +1,157 @@
// license:BSD-3-Clause
// copyright-holders:Ted Green
#include "pci-ide.h"
const device_type IDE_PCI = &device_creator<ide_pci_device>;
ide_pci_device::ide_pci_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: pci_device(mconfig, IDE_PCI, "IDE PCI interface", tag, owner, clock, "ide_pci", __FILE__),
m_ide(*this, "ide"),
m_ide2(*this, "ide2"),
m_irq_num(-1)
{
}
DEVICE_ADDRESS_MAP_START(config_map, 32, ide_pci_device)
AM_RANGE(0x10, 0x17) AM_WRITE(address_base_w)
AM_RANGE(0x40, 0x5f) AM_READWRITE(pcictrl_r, pcictrl_w)
AM_INHERIT_FROM(pci_device::config_map)
ADDRESS_MAP_END
DEVICE_ADDRESS_MAP_START(chan1_data_command_map, 32, ide_pci_device)
AM_RANGE(0x0, 0x7) AM_DEVREADWRITE("ide", bus_master_ide_controller_device, read_cs0, write_cs0)
ADDRESS_MAP_END
DEVICE_ADDRESS_MAP_START(chan1_control_map, 32, ide_pci_device)
AM_RANGE(0x0, 0x3) AM_READWRITE(ide_read_cs1, ide_write_cs1)
ADDRESS_MAP_END
DEVICE_ADDRESS_MAP_START(chan2_data_command_map, 32, ide_pci_device)
AM_RANGE(0x0, 0x7) AM_DEVREADWRITE("ide2", bus_master_ide_controller_device, read_cs0, write_cs0)
ADDRESS_MAP_END
DEVICE_ADDRESS_MAP_START(chan2_control_map, 32, ide_pci_device)
AM_RANGE(0x0, 0x3) AM_READWRITE(ide2_read_cs1, ide2_write_cs1)
ADDRESS_MAP_END
DEVICE_ADDRESS_MAP_START(bus_master_map, 32, ide_pci_device)
AM_RANGE(0x0, 0x7) AM_DEVREADWRITE("ide", bus_master_ide_controller_device, bmdma_r, bmdma_w)
AM_RANGE(0x8, 0xf) AM_DEVREADWRITE("ide2", bus_master_ide_controller_device, bmdma_r, bmdma_w)
ADDRESS_MAP_END
static MACHINE_CONFIG_FRAGMENT(pci_ide)
MCFG_BUS_MASTER_IDE_CONTROLLER_ADD("ide", ata_devices, "hdd", nullptr, true)
MCFG_ATA_INTERFACE_IRQ_HANDLER(WRITELINE(ide_pci_device, ide_interrupt))
//MCFG_BUS_MASTER_IDE_CONTROLLER_SPACE(":maincpu", AS_PROGRAM)
MCFG_BUS_MASTER_IDE_CONTROLLER_SPACE(":pci:00.0", AS_DATA)
MCFG_BUS_MASTER_IDE_CONTROLLER_ADD("ide2", ata_devices, nullptr, "cdrom", true)
MCFG_ATA_INTERFACE_IRQ_HANDLER(WRITELINE(ide_pci_device, ide_interrupt))
//MCFG_BUS_MASTER_IDE_CONTROLLER_SPACE(":maincpu", AS_PROGRAM)
MCFG_BUS_MASTER_IDE_CONTROLLER_SPACE(":pci:00.0", AS_DATA)
MACHINE_CONFIG_END
machine_config_constructor ide_pci_device::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME(pci_ide);
}
void ide_pci_device::set_irq_info(const char *tag, const int irq_num)
{
m_cpu_tag = tag;
m_irq_num = irq_num;
}
void ide_pci_device::device_start()
{
m_cpu = machine().device<cpu_device>(m_cpu_tag);
pci_device::device_start();
add_map(8, M_IO, FUNC(ide_pci_device::chan1_data_command_map));
bank_infos[0].adr = 0x1f0;
add_map(4, M_IO, FUNC(ide_pci_device::chan1_control_map));
bank_infos[1].adr = 0x3f4;
add_map(8, M_IO, FUNC(ide_pci_device::chan2_data_command_map));
bank_infos[2].adr = 0x170;
add_map(4, M_IO, FUNC(ide_pci_device::chan2_control_map));
bank_infos[3].adr = 0x374;
add_map(16, M_IO, FUNC(ide_pci_device::bus_master_map));
bank_infos[4].adr = 0xf00;
}
void ide_pci_device::device_reset()
{
pci_device::device_reset();
}
READ32_MEMBER(ide_pci_device::ide_read_cs1)
{
// PCI offset starts at 0x3f4, idectrl expects 0x3f0
UINT32 data = 0;
data = m_ide->read_cs1(space, ++offset, mem_mask);
return data;
}
WRITE32_MEMBER(ide_pci_device::ide_write_cs1)
{
// PCI offset starts at 0x3f4, idectrl expects 0x3f0
m_ide->write_cs1(space, ++offset, data, mem_mask);
}
READ32_MEMBER(ide_pci_device::ide2_read_cs1)
{
// PCI offset starts at 0x374, idectrl expects 0x370
UINT32 data = 0;
data = m_ide2->read_cs1(space, ++offset, mem_mask);
return data;
}
WRITE32_MEMBER(ide_pci_device::ide2_write_cs1)
{
// PCI offset starts at 0x374, idectrl expects 0x370
m_ide2->write_cs1(space, ++offset, data, mem_mask);
}
WRITE_LINE_MEMBER(ide_pci_device::ide_interrupt)
{
if (m_irq_num != -1) {
m_cpu->set_input_line(m_irq_num, state);
}
if (0)
logerror("%s:ide_interrupt %i set to %i\n", machine().describe_context(), m_irq_num, state);
}
READ32_MEMBER(ide_pci_device::pcictrl_r)
{
return m_config_data[offset];
}
WRITE32_MEMBER(ide_pci_device::pcictrl_w)
{
COMBINE_DATA(&m_config_data[offset]);
}
WRITE32_MEMBER(ide_pci_device::address_base_w)
{
if (1) {
// Bits 0 (ide) and 2 (ide2) control if the mapping is legacy or BAR
switch (offset) {
case 0:
if ((pclass & 0x1) == 0)
data = (data & 0xfffff000) | 0x1f0;
break;
case 1:
if ((pclass & 0x1) == 0)
data = (data & 0xfffff000) | 0x3f4;
break;
case 2:
if ((pclass & 0x4) == 0)
data = (data & 0xfffff000) | 0x170;
break;
default:
if ((pclass & 0x4) == 0)
data = (data & 0xfffff000) | 0x374;
}
}
pci_device::address_base_w(space, offset, data);
}

View File

@ -0,0 +1,65 @@
// license:BSD-3-Clause
// copyright-holders:Ted Green
/***************************************************************************
pci-ide.h
Generic PCI IDE controller implementation.
Based on datasheet for National Semiconductor PC87415
TODO:
Add pci configuration write to PIF byte
***************************************************************************/
#ifndef PCI_IDE_H
#define PCI_IDE_H
#include "pci.h"
#include "idectrl.h"
#define MCFG_IDE_PCI_ADD(_tag, _main_id, _revision, _subdevice_id) \
MCFG_PCI_DEVICE_ADD(_tag, IDE_PCI, _main_id, _revision, 0x01018a, _subdevice_id)
#define MCFG_IDE_PCI_IRQ_ADD(_cpu_tag, _irq_num) \
downcast<ide_pci_device *>(device)->set_irq_info(_cpu_tag, _irq_num);
class ide_pci_device : public pci_device {
public:
ide_pci_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
required_device<bus_master_ide_controller_device> m_ide;
required_device<bus_master_ide_controller_device> m_ide2;
virtual DECLARE_ADDRESS_MAP(config_map, 32) override;
DECLARE_WRITE_LINE_MEMBER(ide_interrupt);
DECLARE_READ32_MEMBER(ide_read_cs1);
DECLARE_WRITE32_MEMBER(ide_write_cs1);
DECLARE_READ32_MEMBER(ide2_read_cs1);
DECLARE_WRITE32_MEMBER(ide2_write_cs1);
void set_irq_info(const char *tag, const int irq_num);
protected:
virtual void device_start() override;
virtual void device_reset() override;
// optional information overrides
virtual machine_config_constructor device_mconfig_additions() const override;
private:
const char *m_cpu_tag;
cpu_device *m_cpu;
int m_irq_num;
int m_irq_status;
UINT32 m_config_data[0x10];
DECLARE_ADDRESS_MAP(chan1_data_command_map, 32);
DECLARE_ADDRESS_MAP(chan1_control_map, 32);
DECLARE_ADDRESS_MAP(chan2_data_command_map, 32);
DECLARE_ADDRESS_MAP(chan2_control_map, 32);
DECLARE_ADDRESS_MAP(bus_master_map, 32);
DECLARE_READ32_MEMBER(pcictrl_r);
DECLARE_WRITE32_MEMBER(pcictrl_w);
DECLARE_WRITE32_MEMBER(address_base_w);
};
extern const device_type IDE_PCI;
#endif

View File

@ -106,11 +106,17 @@ void voodoo_pci_device::device_start()
pci_device::device_start();
if (m_type<=TYPE_VOODOO_2) {
add_map(16*1024*1024, M_MEM | M_PREF, FUNC(voodoo_pci_device::voodoo_reg_map));
bank_infos[0].adr = 0xff000000;
} else {
add_map(32*1024*1024, M_MEM, FUNC(voodoo_pci_device::banshee_reg_map));
add_map(32*1024*1024, M_MEM, FUNC(voodoo_pci_device::lfb_map));
add_map(256, M_IO, FUNC(voodoo_pci_device::io_map));
bank_infos[0].adr = 0xf8000000;
bank_infos[1].adr = 0xf8000008;
bank_infos[2].adr = 0xfffffff0;
}
save_item(NAME(m_pcictrl_reg));
}
void voodoo_pci_device::device_reset()