summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Ted Green <tedgreen99@inbox.com>2016-05-17 11:13:55 -0600
committer Ted Green <tedgreen99@inbox.com>2016-05-17 11:13:55 -0600
commitebe5c6d790c14599a27e53b71c749f44c17fff5d (patch)
tree3a3ee3ba4d0c0ac1e3f191a212b82cb8da30d06d
parent3040c3e65af2a2a6aba353737acddb557b72f6cd (diff)
voodoo_pci: Added default PCI BAR locations (nw)
gt64xxx: Added DMA control and proper PCI address mapping (nw) pci-ide: New generic PCI IDE controller (nw) machine.lua: Added pci-ide machine (nw)
-rw-r--r--scripts/src/machine.lua2
-rw-r--r--src/devices/machine/gt64xxx.cpp400
-rw-r--r--src/devices/machine/gt64xxx.h95
-rw-r--r--src/devices/machine/pci-ide.cpp157
-rw-r--r--src/devices/machine/pci-ide.h65
-rw-r--r--src/devices/video/voodoo_pci.cpp6
6 files changed, 632 insertions, 93 deletions
diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua
index 42a51a6c1e4..1d061199208 100644
--- a/scripts/src/machine.lua
+++ b/scripts/src/machine.lua
@@ -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",
diff --git a/src/devices/machine/gt64xxx.cpp b/src/devices/machine/gt64xxx.cpp
index 4c096af6a3e..c7a4af83633 100644
--- a/src/devices/machine/gt64xxx.cpp
+++ b/src/devices/machine/gt64xxx.cpp
@@ -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));
+
+ // 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);
+ }
- // MIPS drc
- m_cpu->add_fastram(0x1fc00000, 0x1fffffff, TRUE, m_region->base());
+ /* 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);
+ }
+ }
}
diff --git a/src/devices/machine/gt64xxx.h b/src/devices/machine/gt64xxx.h
index 6653c9ca552..91846a8fab7 100644
--- a/src/devices/machine/gt64xxx.h
+++ b/src/devices/machine/gt64xxx.h
@@ -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);
};
diff --git a/src/devices/machine/pci-ide.cpp b/src/devices/machine/pci-ide.cpp
new file mode 100644
index 00000000000..5e89535d13c
--- /dev/null
+++ b/src/devices/machine/pci-ide.cpp
@@ -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);
+}
diff --git a/src/devices/machine/pci-ide.h b/src/devices/machine/pci-ide.h
new file mode 100644
index 00000000000..3a6beea21eb
--- /dev/null
+++ b/src/devices/machine/pci-ide.h
@@ -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
diff --git a/src/devices/video/voodoo_pci.cpp b/src/devices/video/voodoo_pci.cpp
index 9d34442f08b..8d1242713f8 100644
--- a/src/devices/video/voodoo_pci.cpp
+++ b/src/devices/video/voodoo_pci.cpp
@@ -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()