From 52ad1ddaeac1360dd0db480fcf51878fe30e5aba Mon Sep 17 00:00:00 2001 From: Brice Onken <32155223+briceonk@users.noreply.github.com> Date: Mon, 3 Jun 2024 04:25:15 -0700 Subject: sony/news_r3k.cpp: Add support for NEWS-OS 4.1R (#12435) --- src/devices/machine/cxd1185.cpp | 26 +++++++++++++++++++++++--- src/devices/machine/cxd1185.h | 8 ++++++++ src/mame/sony/dmac_0448.cpp | 19 ++++++++++++++----- src/mame/sony/news_r3k.cpp | 2 ++ 4 files changed, 47 insertions(+), 8 deletions(-) diff --git a/src/devices/machine/cxd1185.cpp b/src/devices/machine/cxd1185.cpp index 8b24126b662..12d1d0b73b3 100644 --- a/src/devices/machine/cxd1185.cpp +++ b/src/devices/machine/cxd1185.cpp @@ -261,6 +261,7 @@ void cxd1185_device::command_w(u8 data) m_command = data; m_status |= CIP; + m_last_dma_direction = DMA_NONE; switch (data & (CAT | CMD)) { @@ -304,11 +305,13 @@ void cxd1185_device::command_w(u8 data) LOGMASKED(LOG_CMD, "select target %d without atn\n", (m_scsi_id & TID) >> 5); m_status |= INIT; m_state = ARB_BUS_FREE; + m_last_dma_direction = (m_command & DMA) ? DMA_OUT : DMA_NONE; break; case 0x42: LOGMASKED(LOG_CMD, "select target %d with atn\n", (m_scsi_id & TID) >> 5); m_status |= INIT; m_state = ARB_BUS_FREE; + m_last_dma_direction = (m_command & DMA) ? DMA_OUT : DMA_NONE; break; case 0x43: LOGMASKED(LOG_CMD, "enable selection/reselection\n"); break; case 0x44: LOGMASKED(LOG_CMD, "disable selection/reselection\n"); break; @@ -325,10 +328,12 @@ void cxd1185_device::command_w(u8 data) case 0xc0: LOGMASKED(LOG_CMD, "transfer information\n"); m_state = XFR_INFO; + m_last_dma_direction = (m_command & DMA) ? ((scsi_bus->ctrl_r() & S_INP) ? DMA_IN : DMA_OUT) : DMA_NONE; break; case 0xc1: LOGMASKED(LOG_CMD, "transfer pad\n"); m_state = XFR_INFO; + m_last_dma_direction = (m_command & DMA) ? ((scsi_bus->ctrl_r() & S_INP) ? DMA_IN : DMA_OUT) : DMA_NONE; break; case 0xc2: LOGMASKED(LOG_CMD, "deassert ack\n"); @@ -616,6 +621,11 @@ int cxd1185_device::state_step() // assert ACK scsi_bus->ctrl_w(scsi_refid, S_ACK, S_ACK); + + // If this is a DMA command and we have data now, assert DRQ so host can start transferring + // (also handles transfers in the case where the counter is not aligned with the expected bytes read) + if (m_command & DMA) + set_drq(true); } else { @@ -649,7 +659,8 @@ int cxd1185_device::state_step() // check if target changed phase if (m_int_req[1] & PHC) { - if (m_command & DMA) + // Lower DRQ unless FIFO still has valid data that the host machine can read out + if ((m_command & DMA) && m_fifo.empty()) set_drq(false); m_state = XFR_INFO_DONE; @@ -831,12 +842,21 @@ void cxd1185_device::int_check() { bool irq_asserted = false; + // When SPHI is set during DMA data in, phase change interrupts are deferred until the DMA transfer is complete + // This will be recalculated at that time once the FIFO is empty + uint8_t int_req1 = m_int_req[1]; + if ((m_mode & SPHI) && !m_fifo.empty() && (m_last_dma_direction == DMA_IN) && (int_req1 & PHC)) + { + LOGMASKED(LOG_INT, "SPHI active, suppressing PHC interrupt\n"); + int_req1 &= ~PHC; + } + // update mirq - if (m_int_req[0] || m_int_req[1]) + if (m_int_req[0] || int_req1) { m_status |= MIRQ; - irq_asserted = (m_int_req[0] & m_int_auth[0]) || (m_int_req[1] & m_int_auth[1]); + irq_asserted = (m_int_req[0] & m_int_auth[0]) || (int_req1 & m_int_auth[1]); } else m_status &= ~MIRQ; diff --git a/src/devices/machine/cxd1185.h b/src/devices/machine/cxd1185.h index f1d6732b26d..7fa3f21d7ea 100644 --- a/src/devices/machine/cxd1185.h +++ b/src/devices/machine/cxd1185.h @@ -111,6 +111,13 @@ private: } m_state; + enum dma_direction : u8 + { + DMA_NONE, + DMA_IN, + DMA_OUT + }; + // internal state bool m_irq_asserted; bool m_drq_asserted; @@ -118,6 +125,7 @@ private: bool m_pio_data_mode; bool m_pio_ctrl_mode; u32 m_scsi_ctrl_state; + dma_direction m_last_dma_direction; enum status_mask : u8 { diff --git a/src/mame/sony/dmac_0448.cpp b/src/mame/sony/dmac_0448.cpp index 31dfffd2563..1bedf913f63 100644 --- a/src/mame/sony/dmac_0448.cpp +++ b/src/mame/sony/dmac_0448.cpp @@ -126,8 +126,10 @@ void dmac_0448_device::dma_check(s32 param) if (!(dma.cctl & CS_ENABLE)) return; - // check transfer count - if (!dma.ctrc) + // check transfer count and autopad + // When autopad is enabled, the DMA controller will pad the transaction with 0s + // or discard reads until DRQ is lowered + if (!dma.ctrc && !(dma.cctl & CS_APAD)) return; // TODO: confirm if this is correct @@ -141,12 +143,15 @@ void dmac_0448_device::dma_check(s32 param) LOG("dma_r data 0x%02x address 0x%08x\n", data, address); - m_bus->write_byte(address, data); + if (dma.ctrc > 0) + { + m_bus->write_byte(address, data); + } } else { // memory to device - u8 const data = m_bus->read_byte(address); + u8 const data = dma.ctrc > 0 ? m_bus->read_byte(address) : 0; LOG("dma_w data 0x%02x address 0x%08x\n", data, address); @@ -164,7 +169,11 @@ void dmac_0448_device::dma_check(s32 param) dma.cofs++; // decrement count - dma.ctrc--; + // TODO: Presumably, if autopad is active this doesn't underflow? Needs confirmation on-system, because the above logic depends on this being true. + if (dma.ctrc > 0) + { + dma.ctrc--; + } // set terminal count flag if (!dma.ctrc) diff --git a/src/mame/sony/news_r3k.cpp b/src/mame/sony/news_r3k.cpp index 2d09b4fb48e..7a60064a847 100644 --- a/src/mame/sony/news_r3k.cpp +++ b/src/mame/sony/news_r3k.cpp @@ -516,6 +516,8 @@ void news_r3k_base_state::common(machine_config &config) // scsi bus and devices NSCSI_BUS(config, m_scsibus); // inquiry content for hard disk is "HITACHI DK312C CS01" + // HD CHDs will be treated as MO disks using the inquiry content "SONY SMO-C501 1.00" + // The CHS for converting a raw MO dump for 282MByte per side disks is 18678,1,31 per NEWS-OS 4's disktab file NSCSI_CONNECTOR(config, "scsi:0", news_scsi_devices, "harddisk"); NSCSI_CONNECTOR(config, "scsi:1", news_scsi_devices, nullptr); NSCSI_CONNECTOR(config, "scsi:2", news_scsi_devices, nullptr); -- cgit v1.2.3