// license:BSD-3-Clause // copyright-holders:Patrick Mackinlay /* * An implementation of the SGA (SRX Gate Array) device found in Intergraph * InterPro family systems. There is no public documentation on this device, * so the implementation is being built to follow the logic of the system boot * ROM and its diagnostic tests. * * Please be aware that code in here is not only broken, it's likely wrong in * many cases. * * TODO * - too long to list */ #include "emu.h" #include "interpro_sga.h" #define VERBOSE 0 #include "logmacro.h" void interpro_sga_device::map(address_map &map) { map(0x00, 0x03).rw(FUNC(interpro_sga_device::gcsr_r), FUNC(interpro_sga_device::gcsr_w)); map(0x04, 0x07).rw(FUNC(interpro_sga_device::ipoll_r), FUNC(interpro_sga_device::ipoll_w)); map(0x08, 0x0b).rw(FUNC(interpro_sga_device::imask_r), FUNC(interpro_sga_device::imask_w)); map(0x0c, 0x0f).rw(FUNC(interpro_sga_device::range_base_r), FUNC(interpro_sga_device::range_base_w)); map(0x10, 0x13).rw(FUNC(interpro_sga_device::range_end_r), FUNC(interpro_sga_device::range_end_w)); map(0x14, 0x17).rw(FUNC(interpro_sga_device::cttag_r), FUNC(interpro_sga_device::cttag_w)); // aka diag1 map(0x18, 0x1b).rw(FUNC(interpro_sga_device::address_r), FUNC(interpro_sga_device::address_w)); // aka diag0 map(0x1c, 0x1f).rw(FUNC(interpro_sga_device::dmacsr_r), FUNC(interpro_sga_device::dmacsr_w)); map(0x20, 0x23).rw(FUNC(interpro_sga_device::edmacsr_r), FUNC(interpro_sga_device::edmacsr_w)); // esga map(0x24, 0x27).rw(FUNC(interpro_sga_device::reg6_range_r), FUNC(interpro_sga_device::reg6_range_w)); // esga map(0x80, 0x83).rw(FUNC(interpro_sga_device::ddpta0_r), FUNC(interpro_sga_device::ddpta0_w)); // dma 0 device page table address (esga) map(0x84, 0x87).rw(FUNC(interpro_sga_device::ddpad0_r), FUNC(interpro_sga_device::ddpad0_w)); // dma 0 device page address map(0x88, 0x8b).rw(FUNC(interpro_sga_device::ddoff0_r), FUNC(interpro_sga_device::ddoff0_w)); // dma 0 device page offset map(0x8c, 0x8f).rw(FUNC(interpro_sga_device::ddtc0_r), FUNC(interpro_sga_device::ddtc0_w)); // dma 0 device transfer context map(0x90, 0x93).rw(FUNC(interpro_sga_device::dspta0_r), FUNC(interpro_sga_device::dspta0_w)); // dma 0 SRX page table address (esga) map(0x94, 0x97).rw(FUNC(interpro_sga_device::dspad0_r), FUNC(interpro_sga_device::dspad0_w)); // dma 0 SRX page address map(0x98, 0x9b).rw(FUNC(interpro_sga_device::dsoff0_r), FUNC(interpro_sga_device::dsoff0_w)); // dma 0 SRX page offset map(0x9c, 0x9f).rw(FUNC(interpro_sga_device::dstc0_r), FUNC(interpro_sga_device::dstc0_w)); // dma 0 SRX transfer context map(0xa4, 0xa7).rw(FUNC(interpro_sga_device::dspad1_r), FUNC(interpro_sga_device::dspad1_w)); // dma 1 source page address map(0xa8, 0xab).rw(FUNC(interpro_sga_device::dsoff1_r), FUNC(interpro_sga_device::dsoff1_w)); // dma 1 source page offset map(0xac, 0xaf).rw(FUNC(interpro_sga_device::dstc1_r), FUNC(interpro_sga_device::dstc1_w)); // dma 1 source transfer count map(0xb4, 0xb7).rw(FUNC(interpro_sga_device::ddpad1_r), FUNC(interpro_sga_device::ddpad1_w)); // dma 1 destination page address map(0xb8, 0xbb).rw(FUNC(interpro_sga_device::ddoff1_r), FUNC(interpro_sga_device::ddoff1_w)); // dma 1 destination page offset map(0xbc, 0xbf).rw(FUNC(interpro_sga_device::ddtc1_r), FUNC(interpro_sga_device::ddtc1_w)); // dma 1 destination transfer count map(0xc0, 0xc3).rw(FUNC(interpro_sga_device::ddpta2_r), FUNC(interpro_sga_device::ddpta2_w)); // dma 2 device page table address (esga) map(0xc4, 0xc7).rw(FUNC(interpro_sga_device::ddpad2_r), FUNC(interpro_sga_device::ddpad2_w)); // dma 2 device page address map(0xc8, 0xcb).rw(FUNC(interpro_sga_device::ddoff2_r), FUNC(interpro_sga_device::ddoff2_w)); // dma 2 device page offset map(0xcc, 0xcf).rw(FUNC(interpro_sga_device::ddtc2_r), FUNC(interpro_sga_device::ddtc2_w)); // dma 2 device transfer context map(0xd0, 0xd3).rw(FUNC(interpro_sga_device::dspta2_r), FUNC(interpro_sga_device::dspta2_w)); // dma 2 SRX page table address (esga) map(0xd4, 0xd7).rw(FUNC(interpro_sga_device::dspad2_r), FUNC(interpro_sga_device::dspad2_w)); // dma 2 SRX page address map(0xd8, 0xdb).rw(FUNC(interpro_sga_device::dsoff2_r), FUNC(interpro_sga_device::dsoff2_w)); // dma 2 SRX page offset map(0xdc, 0xdf).rw(FUNC(interpro_sga_device::dstc2_r), FUNC(interpro_sga_device::dstc2_w)); // dma 2 SRX transfer context map(0xe0, 0xe3).rw(FUNC(interpro_sga_device::ddrd2_r), FUNC(interpro_sga_device::ddrd2_w)); // dma 2 device record descriptor (esga) map(0xe4, 0xe7).rw(FUNC(interpro_sga_device::dsrd2_r), FUNC(interpro_sga_device::dsrd2_w)); // dma 2 SRX record descriptor (esga) map(0xe8, 0xeb).rw(FUNC(interpro_sga_device::dcksum0_r), FUNC(interpro_sga_device::dcksum0_w)); // dma 1 device checksum register 0 (esga) map(0xec, 0xef).rw(FUNC(interpro_sga_device::dcksum1_r), FUNC(interpro_sga_device::dcksum1_w)); // dma 1 device checksum register 1 (esga) } DEFINE_DEVICE_TYPE(INTERPRO_SGA, interpro_sga_device, "sga", "SRX Gate Array") interpro_sga_device::interpro_sga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, INTERPRO_SGA, tag, owner, clock) , m_berr_func(*this) { } void interpro_sga_device::device_start() { m_berr_func.resolve(); save_item(NAME(m_gcsr)); save_item(NAME(m_ipoll)); save_item(NAME(m_imask)); save_item(NAME(m_range_base)); save_item(NAME(m_range_end)); save_item(NAME(m_cttag)); save_item(NAME(m_address)); save_item(NAME(m_dmacsr)); save_item(NAME(m_edmacsr)); save_item(NAME(m_reg6_range)); save_item(NAME(m_ddpta0)); save_item(NAME(m_ddpad0)); save_item(NAME(m_ddoff0)); save_item(NAME(m_ddtc0)); save_item(NAME(m_dspta0)); save_item(NAME(m_dspad0)); save_item(NAME(m_dsoff0)); save_item(NAME(m_dstc0)); save_item(NAME(m_dspad1)); save_item(NAME(m_dsoff1)); save_item(NAME(m_dstc1)); save_item(NAME(m_ddpad1)); save_item(NAME(m_ddoff1)); save_item(NAME(m_ddtc1)); save_item(NAME(m_ddpta2)); save_item(NAME(m_ddpad2)); save_item(NAME(m_ddoff2)); save_item(NAME(m_ddtc2)); save_item(NAME(m_dspta2)); save_item(NAME(m_dspad2)); save_item(NAME(m_dsoff2)); save_item(NAME(m_dstc2)); save_item(NAME(m_ddrd2)); save_item(NAME(m_dsrd2)); save_item(NAME(m_dcksum0)); save_item(NAME(m_dcksum1)); } void interpro_sga_device::device_reset() { } void interpro_sga_device::ddtc1_w(u32 data) { m_ddtc1 = data; // assume that when this register is written, we should start a // memory to memory dma transfer LOG(" gcsr = 0x%08x dmacsr = 0x%08x\n", m_gcsr, m_dmacsr); LOG(" ipoll = 0x%08x imask = 0x%08x\n", m_ipoll, m_imask); LOG("dspad1 = 0x%08x dsoff1 = 0x%08x dstc1 = 0x%08x\n", m_dspad1, m_dsoff1, m_dstc1); LOG("ddpad1 = 0x%08x ddoff1 = 0x%08x ddtc1 = 0x%08x\n", m_ddpad1, m_ddoff1, m_ddtc1); // when complete, we indicate by setting DMAEND(2) - 2 is probably the channel // we also turn off the INTBERR and INTMMBE flags m_ipoll &= ~(IPOLL_INTBERR | IPOLL_INTMMBE); m_ipoll |= 0x200; #if 0 // if the address is invalid, fake a bus error if ((m_dspad1 & 0xfffff000) == 0x40000000 || (m_ddpad1 & 0xfffff) == 0x40000000) { m_ipoll |= IPOLL_INTBERR; // error cycle - bit 0x10 indicates source address error (dspad1) // now expecting 0x5463? if ((m_dspad1 & 0xfffff000) == 0x40000000) m_berr_func(space, 0x5433, m_dspad1); // BINFO_SNAPOK | BINFO_BERR | BINFO_BG_ICAMMU | 0x30 | CT(3) else m_berr_func(space, 0x5423, m_ddpad1); // BINFO_SNAPOK | BINFO_BERR | BINFO_BG_ICAMMU | 0x20 | CT(3) // 0x5423 = BERR|SNAPOK | BG(ICAMMU)? | CT(23) // 0x5433 = BERR|SNAPOK | BG(ICAMMU)? | CT(33) // 0x5463 = BERR|SNAPOK | BG(ICAMMU)? | TAG(40=1) | CT(23) } #endif }