diff --git a/src/mame/drivers/interpro.cpp b/src/mame/drivers/interpro.cpp index 8747c865ad0..1064cadbaa1 100644 --- a/src/mame/drivers/interpro.cpp +++ b/src/mame/drivers/interpro.cpp @@ -3,8 +3,6 @@ #include "emu.h" -#define NEW_SCSI 1 - #include "includes/interpro.h" #include "debugger.h" @@ -262,7 +260,6 @@ READ8_MEMBER(interpro_state::rtc_r) READ8_MEMBER(interpro_state::scsi_r) { -#if NEW_SCSI switch (offset >> 6) { case 0x0: return m_scsi->tcounter_lo_r(space, 0); @@ -275,19 +272,14 @@ READ8_MEMBER(interpro_state::scsi_r) case 0x7: return m_scsi->fifo_flags_r(space, 0); case 0x8: return m_scsi->conf_r(space, 0); case 0xb: return m_scsi->conf2_r(space, 0); - case 0xc: return m_scsi->conf3_r(space, 0); } - logerror("read unmapped scsi adapter register 0x%x\n", offset >> 6); - return 0x00; -#else - return m_scsi->read(space, offset >> 6, mem_mask); -#endif + logerror("scsi: read unmapped register 0x%x (%s)\n", offset >> 6, machine().describe_context()); + return space.unmap(); } WRITE8_MEMBER(interpro_state::scsi_w) { -#if NEW_SCSI switch (offset >> 6) { case 0: m_scsi->tcount_lo_w(space, 0, data); return; @@ -302,36 +294,9 @@ WRITE8_MEMBER(interpro_state::scsi_w) case 9: m_scsi->clock_w(space, 0, data); return; case 0xa: m_scsi->test_w(space, 0, data); return; case 0xb: m_scsi->conf2_w(space, 0, data); return; - case 0xc: m_scsi->conf3_w(space, 0, data); return; - case 0xf: m_scsi->fifo_align_w(space, 0, data); return; } - logerror("unmapped scsi register write 0x%02x data 0x%02x\n", offset >> 6, data); -#else - m_scsi->write(space, offset >> 6, data, mem_mask); -#endif -} - -READ8_MEMBER(interpro_state::scsi_dma_r) -{ -#if NEW_SCSI - return m_scsi->dma_r(); -#else - u8 data = 0; - - m_scsi->dma_read_data(1, &data); - - return data; -#endif -} - -WRITE8_MEMBER(interpro_state::scsi_dma_w) -{ -#if NEW_SCSI - m_scsi->dma_w(data); -#else - m_scsi->dma_write_data(1, &data); -#endif + logerror("scsi: unmapped register write 0x%02x data 0x%02x (%s)\n", offset >> 6, data, machine().describe_context()); } DRIVER_INIT_MEMBER(interpro_state, ip2800) @@ -351,19 +316,17 @@ DRIVER_INIT_MEMBER(interpro_state, ip2800) space.install_ram(0, m_ram->mask(), m_ram->pointer()); } -#if NEW_SCSI static SLOT_INTERFACE_START(interpro_scsi_devices) SLOT_INTERFACE("harddisk", NSCSI_HARDDISK) SLOT_INTERFACE("cdrom", NSCSI_CDROM) - SLOT_INTERFACE_INTERNAL(INTERPRO_SCSI_ADAPTER_TAG, NCR53C94) + SLOT_INTERFACE_INTERNAL(INTERPRO_SCSI_ADAPTER_TAG, NCR53C90A) SLOT_INTERFACE_END static MACHINE_CONFIG_START(interpro_scsi_adapter) - MCFG_DEVICE_CLOCK(XTAL_12_5MHz) + MCFG_DEVICE_CLOCK(XTAL_24MHz) MCFG_NCR5390_IRQ_HANDLER(DEVWRITELINE(":" INTERPRO_IOGA_TAG, interpro_ioga_device, ir0_w)) MCFG_NCR5390_DRQ_HANDLER(DEVWRITELINE(":" INTERPRO_IOGA_TAG, interpro_ioga_device, drq_scsi)) MACHINE_CONFIG_END -#endif // these maps point the cpu virtual addresses to the mmu static ADDRESS_MAP_START(clipper_insn_map, AS_PROGRAM, 32, interpro_state) @@ -503,7 +466,6 @@ static MACHINE_CONFIG_START(ip2800) MCFG_FLOPPY_DRIVE_SOUND(false) // scsi -#if NEW_SCSI MCFG_NSCSI_BUS_ADD(INTERPRO_SCSI_TAG) MCFG_NSCSI_ADD(INTERPRO_SCSI_TAG ":0", interpro_scsi_devices, "harddisk", false) MCFG_NSCSI_ADD(INTERPRO_SCSI_TAG ":1", interpro_scsi_devices, nullptr, false) @@ -514,16 +476,6 @@ static MACHINE_CONFIG_START(ip2800) MCFG_NSCSI_ADD(INTERPRO_SCSI_TAG ":6", interpro_scsi_devices, nullptr, false) MCFG_NSCSI_ADD(INTERPRO_SCSI_TAG ":7", interpro_scsi_devices, INTERPRO_SCSI_ADAPTER_TAG, true) MCFG_DEVICE_CARD_MACHINE_CONFIG(INTERPRO_SCSI_ADAPTER_TAG, interpro_scsi_adapter) -#else - MCFG_DEVICE_ADD(INTERPRO_SCSI_TAG, SCSI_PORT, 0) - MCFG_SCSIDEV_ADD(INTERPRO_SCSI_TAG ":" SCSI_PORT_DEVICE1, "harddisk", SCSIHD, SCSI_ID_0) - MCFG_SCSIDEV_ADD(INTERPRO_SCSI_TAG ":" SCSI_PORT_DEVICE3, "cdrom", SCSICD, SCSI_ID_3) - - MCFG_DEVICE_ADD(INTERPRO_SCSI_ADAPTER_TAG, NCR539X, XTAL_12_5MHz) - MCFG_LEGACY_SCSI_PORT(INTERPRO_SCSI_TAG) - MCFG_NCR539X_OUT_IRQ_CB(DEVWRITELINE(INTERPRO_IOGA_TAG, interpro_ioga_device, ir0_w)) - MCFG_NCR539X_OUT_DRQ_CB(DEVWRITELINE(INTERPRO_IOGA_TAG, interpro_ioga_device, drq_scsi)) -#endif // i/o gate array MCFG_INTERPRO_IOGA_ADD(INTERPRO_IOGA_TAG) @@ -531,9 +483,7 @@ static MACHINE_CONFIG_START(ip2800) MCFG_INTERPRO_IOGA_IRQ_CB(INPUTLINE(INTERPRO_CPU_TAG, INPUT_LINE_IRQ0)) //MCFG_INTERPRO_IOGA_DMA_CB(IOGA_DMA_CHANNEL_PLOTTER, unknown) - // use driver helper functions to wrap scsi adapter dma read/write - MCFG_INTERPRO_IOGA_DMA_CB(IOGA_DMA_SCSI, DEVREAD8("", interpro_state, scsi_dma_r), DEVWRITE8("", interpro_state, scsi_dma_w)) - + MCFG_INTERPRO_IOGA_DMA_CB(IOGA_DMA_SCSI, DEVREAD8(INTERPRO_SCSI_DEVICE_TAG, ncr53c90a_device, mdma_r), DEVWRITE8(INTERPRO_SCSI_DEVICE_TAG, ncr53c90a_device, mdma_w)) MCFG_INTERPRO_IOGA_DMA_CB(IOGA_DMA_FLOPPY, DEVREAD8(INTERPRO_FDC_TAG, n82077aa_device, mdma_r), DEVWRITE8(INTERPRO_FDC_TAG, n82077aa_device, mdma_w)) MCFG_INTERPRO_IOGA_DMA_CB(IOGA_DMA_SERIAL, DEVREAD8(INTERPRO_SCC1_TAG, z80scc_device, da_r), DEVWRITE8(INTERPRO_SCC1_TAG, z80scc_device, da_w)) MCFG_INTERPRO_IOGA_FDCTC_CB(DEVWRITELINE(INTERPRO_FDC_TAG, n82077aa_device, tc_line_w)) diff --git a/src/mame/includes/interpro.h b/src/mame/includes/interpro.h index 021dfc50325..543cb147285 100644 --- a/src/mame/includes/interpro.h +++ b/src/mame/includes/interpro.h @@ -19,19 +19,12 @@ #include "machine/z80scc.h" #include "machine/mc146818.h" #include "machine/upd765.h" -#if NEW_SCSI -#include "machine/ncr5390.h" +#include "machine/ncr5390.h" #include "machine/nscsi_bus.h" #include "machine/nscsi_cd.h" #include "machine/nscsi_hd.h" -#else -#include "machine/ncr539x.h" -#include "bus/scsi/scsi.h" -#include "bus/scsi/scsicd.h" -#include "bus/scsi/scsihd.h" -#endif #include "bus/rs232/rs232.h" #include "formats/pc_dsk.h" @@ -52,6 +45,7 @@ #define INTERPRO_FDC_TAG "fdc" #define INTERPRO_SCSI_TAG "scsi" #define INTERPRO_SCSI_ADAPTER_TAG "adapter" +#define INTERPRO_SCSI_DEVICE_TAG INTERPRO_SCSI_TAG ":7:" INTERPRO_SCSI_ADAPTER_TAG #define INTERPRO_IOGA_TAG "ioga" #define INTERPRO_MCGA_TAG "mcga" @@ -70,12 +64,8 @@ public: m_scc2(*this, INTERPRO_SCC2_TAG), m_rtc(*this, INTERPRO_RTC_TAG), m_fdc(*this, INTERPRO_FDC_TAG), -#if NEW_SCSI m_scsibus(*this, INTERPRO_SCSI_TAG), - m_scsi(*this, INTERPRO_SCSI_TAG ":7:" INTERPRO_SCSI_ADAPTER_TAG), -#else - m_scsi(*this, INTERPRO_SCSI_ADAPTER_TAG), -#endif + m_scsi(*this, INTERPRO_SCSI_DEVICE_TAG), m_ioga(*this, INTERPRO_IOGA_TAG), m_mcga(*this, INTERPRO_MCGA_TAG), m_sga(*this, INTERPRO_SGA_TAG), @@ -92,13 +82,8 @@ public: required_device m_scc2; required_device m_rtc; required_device m_fdc; -#if NEW_SCSI required_device m_scsibus; - required_device m_scsi; -#else - required_device m_scsi; -#endif - + required_device m_scsi; required_device m_ioga; required_device m_mcga; required_device m_sga; @@ -137,9 +122,9 @@ public: CTRL1_FLOPRDY = 0x0002, CTRL1_LEDENA = 0x0004, CTRL1_LEDDP = 0x0008, - CTRL1_ETHLOOP = 0x0010, + CTRL1_ETHLOOP = 0x0010, // remote modem loopback CTRL1_ETHDTR = 0x0020, - CTRL1_ETHRMOD = 0x0040, + CTRL1_ETHRMOD = 0x0040, // remote modem configured active low CTRL1_CLIPRESET = 0x0040, CTRL1_FIFOACTIVE = 0x0080 }; @@ -176,8 +161,6 @@ public: DECLARE_READ8_MEMBER(scsi_r); DECLARE_WRITE8_MEMBER(scsi_w); - DECLARE_READ8_MEMBER(scsi_dma_r); - DECLARE_WRITE8_MEMBER(scsi_dma_w); DECLARE_FLOPPY_FORMATS(floppy_formats); diff --git a/src/mame/machine/interpro_ioga.cpp b/src/mame/machine/interpro_ioga.cpp index 236b64b0d7b..010791f5165 100644 --- a/src/mame/machine/interpro_ioga.cpp +++ b/src/mame/machine/interpro_ioga.cpp @@ -18,10 +18,13 @@ #include "emu.h" #include "interpro_ioga.h" +// the following enables some hacks which will allow all iogadiag tests to complete successfully, but also breaks scsi dma +#define IOGA_DMA_DIAG_HACK 0 + #define LOG_GENERAL (1 << 31) -#define LOG_HWINT_ENABLE 0 //((1<<3) | LOG_GENERAL) -#define LOG_DMA_ENABLE ((1<enable(false); - // allocate timer for DMA controller - m_dma_timer = timer_alloc(IOGA_TIMER_DMA); - m_dma_timer->adjust(attotime::never); - + // allocate ioga interrupt and dma timer m_ioga_clock = timer_alloc(IOGA_CLOCK); m_ioga_clock->adjust(attotime::never); } @@ -157,7 +163,7 @@ void interpro_ioga_device::device_reset() m_timer_reg[0] = 0; //m_timer[0]->adjust(attotime::zero, IOGA_TIMER_0, attotime::from_hz(60)); - // configure ioga clock timer + // configure ioga interrupt and dma timer m_ioga_clock->adjust(attotime::zero, IOGA_CLOCK, attotime::from_hz(clock())); } @@ -282,12 +288,9 @@ void interpro_ioga_device::device_timer(emu_timer &timer, device_timer_id id, in } break; - case IOGA_TIMER_DMA: - dma_clock(param); - break; - case IOGA_CLOCK: interrupt_clock(); + dma_clock(); break; } } @@ -482,7 +485,8 @@ void interpro_ioga_device::interrupt_clock() if (m_nmi_pending) { // check if nmi is enabled - if ((m_nmictrl & NMI_IE) == NMI_IE) + if (((m_nmictrl & NMI_IE) == NMI_IE) + || ((m_nmictrl & (NMI_ALL | NMI_ENABLE1)) == (NMI_ALL | NMI_ENABLE1))) { LOG_INTERRUPT("nmi: accepting nmi\n"); @@ -607,7 +611,10 @@ WRITE8_MEMBER(interpro_ioga_device::nmictrl_w) // check for a forced nmi (NMI_NEGPOL written from 1 to 0 with NMI_IE set) if ((m_nmictrl & NMI_NEGPOL) && (data & (NMI_NEGPOL | NMI_IE)) == NMI_IE) + { + LOG_INTERRUPT("nmi: forced nmi\n"); m_nmi_pending = true; + } m_nmictrl = data; } @@ -628,136 +635,223 @@ WRITE16_MEMBER(interpro_ioga_device::softint_vector_w) /****************************************************************************** DMA ******************************************************************************/ -void interpro_ioga_device::dma_clock(int channel) +void interpro_ioga_device::dma_clock() { - struct dma &dma_channel = m_dma_channel[channel]; - - // if bus grant is not enabled, set the busy flag (iogadiag test 7.0265) - if (!(m_arbctl & dma_channel.arb_mask)) + for (auto &dma_channel : m_dma_channel) { - dma_channel.control |= DMA_CTRL_BUSY; - m_dma_channel[channel].control |= DMA_CTRL_BUSY; - m_dma_timer->adjust(attotime::from_hz(clock()), channel); - - return; - } - else - dma_channel.control &= ~DMA_CTRL_BUSY; - - // if the channel isn't active yet, make it active and log something - if (!dma_channel.dma_active) - { - LOG_DMA(channel, "dma: transfer %s device begun, channel = %d, control 0x%08x, real address 0x%08x, virtual address 0x%08x, count 0x%08x\n", - (dma_channel.control & DMA_CTRL_WRITE) ? "to" : "from", - channel, dma_channel.control, dma_channel.real_address, dma_channel.virtual_address, dma_channel.transfer_count); - dma_channel.dma_active = true; - } - - // transfer data while the device is requesting a data transfer and the transfer count is not zero - while (dma_channel.drq_state && dma_channel.transfer_count) - { - // transfer from the memory to device or device to memory - if (dma_channel.control & DMA_CTRL_WRITE) - dma_channel.device_w(m_memory_space->read_byte(dma_channel.real_address)); - else - m_memory_space->write_byte(dma_channel.real_address, dma_channel.device_r()); - - // increment addresses and decrement count - dma_channel.real_address++; - dma_channel.virtual_address++; - dma_channel.transfer_count--; - } - - // if there are no more bytes remaining, terminate the transfer - if (dma_channel.transfer_count == 0) - { - LOG_DMA(channel, "dma: transfer %s device ended, channel = %d, control 0x%08x, real address 0x%08x, virtual address 0x%08x, count 0x%08x\n", - (dma_channel.control & DMA_CTRL_WRITE) ? "to" : "from", - channel, dma_channel.control, dma_channel.real_address, dma_channel.virtual_address, dma_channel.transfer_count); - - if (channel == IOGA_DMA_FLOPPY) + switch (dma_channel.state) { - LOG_DMA(channel, "dma: asserting fdc terminal count line\n"); + case IDLE: + break; - m_fdc_tc_func(ASSERT_LINE); - m_fdc_tc_func(CLEAR_LINE); + case COMMAND: + // start a command + // HACK: busy flag indicates bus access required? + if (dma_channel.control & DMA_CTRL_BUSY) + dma_channel.state = WAIT; + else + dma_channel.state = COMPLETE; + break; + + case WAIT: + // if bus grant is enabled, clear wait flag and execute transfer + if (m_arbctl & dma_channel.arb_mask) + { + // clear bus wait flag + dma_channel.control &= ~DMA_CTRL_WAIT; + + LOG_DMA(dma_channel.channel, "dma: transfer %s device begun, channel = %d, control 0x%08x, real address 0x%08x, virtual address 0x%08x, count 0x%08x\n", + (dma_channel.control & DMA_CTRL_WRITE) ? "to" : "from", + dma_channel.channel, dma_channel.control, dma_channel.real_address, dma_channel.virtual_address, dma_channel.transfer_count); + + dma_channel.state = TRANSFER; + } + else + // (7.0265) set the bus grant wait flag + dma_channel.control |= DMA_CTRL_WAIT; + break; + + case TRANSFER: + // if there are no more bytes remaining, terminate the transfer + if (dma_channel.transfer_count == 0) + { + LOG_DMA(dma_channel.channel, "dma: transfer %s device ended, channel = %d, control 0x%08x, real address 0x%08x, virtual address 0x%08x, count 0x%08x\n", + (dma_channel.control & DMA_CTRL_WRITE) ? "to" : "from", + dma_channel.channel, dma_channel.control, dma_channel.real_address, dma_channel.virtual_address, dma_channel.transfer_count); + + if (dma_channel.channel == IOGA_DMA_FLOPPY) + { + LOG_DMA(dma_channel.channel, "dma: asserting fdc terminal count line\n"); + + m_fdc_tc_func(ASSERT_LINE); + m_fdc_tc_func(CLEAR_LINE); + } + + // set transfer count zero flag + dma_channel.control |= DMA_CTRL_TCZERO; + dma_channel.state = COMPLETE; + } +#if IOGA_DMA_DIAG_HACK + else +#define TAG ((dma_channel.control & DMA_CTRL_TAG) >> 3) + + // hacks for forced dma bus error diagnostic tests + if ((dma_channel.control & 0xfe000000 && dma_channel.control & 0xe00) || ((dma_channel.control & DMA_CTRL_WMASK) == 0x41000000)) + if (dma_channel.real_address & 0xff000000 || dma_channel.real_address == 0) + { + LOG_DMA(dma_channel.channel, "dma: forced bus error hack, control 0x%08x\n", dma_channel.control); + + // (7.0267) trigger an interrupt + m_hwicr[dma_channel.channel + 1] |= IOGA_INTERRUPT_PENDING; + + // (7.0268) set bus error bit + dma_channel.control |= DMA_CTRL_BERR; + + // 7.0269, 7.0276, 7.0281, 7.0289: set error address from virtual or real dma address + // HACK: don't set error address for 7.0276 special case + if (!(dma_channel.control == 0x65400600 && dma_channel.real_address != 0)) + m_error_address = dma_channel.control & DMA_CTRL_VIRTUAL ? dma_channel.virtual_address : dma_channel.real_address; + + // compute bus error cycle type from control register + u8 cycle_type = 0x30; + switch ((dma_channel.control >> 24) & 0x8c) + { + case 0x00: cycle_type |= 2; break; + case 0x04: cycle_type |= 1; break; + case 0x08: cycle_type |= 3; break; + case 0x80: cycle_type |= 4; break; + case 0x84: cycle_type |= 8; break; + } + + switch (dma_channel.control & ~DMA_CTRL_BERR) + { + case 0x61000800: // VIRTUAL | WRITE | TAG(3) + // (7.0266) trigger an nmi + m_nmi_pending = true; + + // (7.0270) set error cycle type 0x52f0: SNAPOK | BERR | BG(IOD) | TAG(0c0) | CT(30) + m_error_businfo = BINFO_SNAPOK | BINFO_BERR | BINFO_BG_IOD | 0xf0; + break; + + case 0x65000600: // VIRTUAL | WRITE | X | TAG(4) + if (dma_channel.real_address != 0) + { + // (7.0275) control register expect 0x64400800 + dma_channel.control &= ~0x600; + dma_channel.control |= 0x800; + + // (7.0277) set error cycle type 0x5331: SNAPOK | BERR | BG(IOD) | TAG(100) | CT(31) + m_error_businfo = BINFO_SNAPOK | BINFO_BERR | BINFO_BG_IOD | TAG | cycle_type; + } + else + { + // (7.0287) set error cycle type 0x62f0: SNAPOK | MMBE | BG(IOD) | TAG(0c0) | CT(30) + m_error_businfo = BINFO_SNAPOK | BINFO_MMBE | BINFO_BG_IOD | TAG | 0x30; + } + break; + + default: + m_error_businfo = BINFO_SNAPOK | BINFO_BERR | BINFO_BG_IOD | TAG | cycle_type; + break; + } + + dma_channel.state = COMPLETE; + } +#endif + break; + + case COMPLETE: + // clear busy flag + dma_channel.control &= ~DMA_CTRL_BUSY; + dma_channel.state = IDLE; + break; } - - dma_channel.control |= DMA_CTRL_TCZERO; - dma_channel.dma_active = false; } } void interpro_ioga_device::drq(int state, int channel) { - // a device is requesting a dma data transfer (read or write) - m_dma_channel[channel].drq_state = state; + // TODO: implement virtual addressing when DMA_CTRL_VIRTUAL is set + + struct dma &dma_channel = m_dma_channel[channel]; if (state) { LOG_DMA(channel, "dma: drq for channel %d asserted\n", channel); - m_dma_timer->adjust(attotime::zero, channel); + if (dma_channel.state == TRANSFER && dma_channel.transfer_count) + { + // transfer from the memory to device or device to memory + if (dma_channel.control & DMA_CTRL_WRITE) + dma_channel.device_w(m_memory_space->read_byte(dma_channel.real_address)); + else + m_memory_space->write_byte(dma_channel.real_address, dma_channel.device_r()); + + // increment addresses and decrement count + dma_channel.real_address++; + dma_channel.virtual_address++; + dma_channel.transfer_count--; + } } else LOG_DMA(channel, "dma: drq for channel %d deasserted\n", channel); } -/* -0x94: error address reg: expect 0x7f200000 after bus error (from dma virtual address) -0x98: error cycle type: expect 0x52f0 (after failed dma?) - 0x5331 - forced berr with nmi/interrupts disabled? - 0xc2f0 - 0x62f0 -*/ -// TODO: 7.0266 - forced BERR not working u32 interpro_ioga_device::dma_r(address_space &space, offs_t offset, u32 mem_mask, int channel) { + struct dma &dma_channel = m_dma_channel[channel]; + switch (offset) { case 0: - return m_dma_channel[channel].real_address; + return dma_channel.real_address; case 1: - return m_dma_channel[channel].virtual_address; + return dma_channel.virtual_address; case 2: - return m_dma_channel[channel].transfer_count; + return dma_channel.transfer_count; case 3: - return m_dma_channel[channel].control; - } + return dma_channel.control; - logerror("dma_r: unknown channel %d\n", channel); - return 0; + default: + logerror("dma_r: unknown dma register %d\n", offset); + return 0; + } } void interpro_ioga_device::dma_w(address_space &space, offs_t offset, u32 data, u32 mem_mask, int channel) { + struct dma &dma_channel = m_dma_channel[channel]; + switch (offset) { case 0: LOG_DMA(channel, "dma: channel %d real address = 0x%08x (%s)\n", channel, data, machine().describe_context()); - m_dma_channel[channel].real_address = data; + dma_channel.real_address = data; break; case 1: LOG_DMA(channel, "dma: channel %d virtual address = 0x%08x (%s)\n", channel, data, machine().describe_context()); - m_dma_channel[channel].virtual_address = data & ~0x3; + dma_channel.virtual_address = data & ~0x3; break; case 2: LOG_DMA(channel, "dma: channel %d transfer count = 0x%08x (%s)\n", channel, data, machine().describe_context()); - m_dma_channel[channel].transfer_count = data; + dma_channel.transfer_count = data; break; case 3: LOG_DMA(channel, "dma: channel %d control = 0x%08x (%s)\n", channel, data, machine().describe_context()); - m_dma_channel[channel].control = data & DMA_CTRL_WMASK; - // start a forced dma transfer if necessary - if ((data & DMA_CTRL_FORCED) == DMA_CTRL_FORCED) - m_dma_timer->adjust(attotime::from_hz(clock()), channel); + // (7.0272) if bus error flag is set, clear existing bus error (otherwise retain existing state) + if (data & DMA_CTRL_BERR) + dma_channel.control = data & DMA_CTRL_WMASK; + else + dma_channel.control = (data & DMA_CTRL_WMASK) | (dma_channel.control & DMA_CTRL_BERR); + + dma_channel.state = COMMAND; break; } } @@ -806,3 +900,41 @@ WRITE16_MEMBER(interpro_ioga_device::arbctl_w) m_arbctl = data; } + +WRITE32_MEMBER(interpro_ioga_device::eth_remap_w) +{ + LOG_ETH("eth: remap = 0x%08x (%s)\n", data, machine().describe_context()); + + m_eth_remap = data & ~0xf; +} + +WRITE32_MEMBER(interpro_ioga_device::eth_map_page_w) +{ + LOG_ETH("eth: remap page = 0x%08x (%s)\n", data, machine().describe_context()); + + m_eth_map_page = data & ~0xf; +} + +WRITE32_MEMBER(interpro_ioga_device::eth_control_w) +{ + LOG_ETH("eth: control = 0x%08x (%s)\n", data, machine().describe_context()); + + /* (7.0202) eth ctrl register input test patterns and expected outputs are: + + 7809 -> 4000 + + 3809 -> 0800 + 3409 -> 0400 + 3209 -> 0200 + 3109 -> 0100 + + 3089 -> 80 + 3049 -> 40 + 3019 -> 10 + 300b -> 02 + */ + if (data & ETH_RESET) + m_eth_control = ETH_RESET; + else + m_eth_control = data & 0x0ff2; +} diff --git a/src/mame/machine/interpro_ioga.h b/src/mame/machine/interpro_ioga.h index ee8af40f5a4..f852ed5b985 100644 --- a/src/mame/machine/interpro_ioga.h +++ b/src/mame/machine/interpro_ioga.h @@ -60,26 +60,6 @@ #define IOGA_DMA_FLOPPY 2 #define IOGA_DMA_SERIAL 3 -// dma control register - -// are these "commands"? -#define IOGA_DMA_CTRL_RESET_L 0x61000000 // do not clear bus error bit -#define IOGA_DMA_CTRL_RESET 0x60400000 // clear bus error bit - -// uncertain about these -#define IOGA_DMA_CTRL_START 0x10000000 -#define IOGA_DMA_CTRL_ENABLE 0x20000000 -#define IOGA_DMA_CTRL_X 0x00800000 // another error bit? -#define IOGA_DMA_CTRL_Y 0x01000000 // turned off if either of two above are found - -#define IOGA_DMA_CTRL_UNK1 0x60000000 // don't know yet -#define IOGA_DMA_CTRL_UNK2 0x67000600 // forced berr with nmi and interrupts disabled -#define IOGA_DMA_CTRL_UNK3 0xbf000600 // set by scsidiag before executing scsi "transfer information" command - -// read values -// iogadiag expects 0x64400800 after forced berr with nmi/interrupts disabled - - class interpro_ioga_device : public device_t { public: @@ -117,6 +97,45 @@ public: DECLARE_WRITE_LINE_MEMBER(drq_scsi) { drq(state, IOGA_DMA_SCSI); } DECLARE_WRITE_LINE_MEMBER(drq_floppy) { drq(state, IOGA_DMA_FLOPPY); } + enum eth_remap_mask + { + ETH_REMAP_CHA_FLUSH = 0x00000008, + ETH_REMAP_CHA_BUF = 0x00000010, + ETH_REMAP_CHA_QUAD = 0x00000020, + ETH_REMAP_CHA_WTAG = 0x000001c0, + ETH_REMAP_CHA_RTAG = 0x00000e00, + ETH_REMAP_ADDR = 0xfffff000 + }; + DECLARE_READ32_MEMBER(eth_remap_r) { return m_eth_remap; } + DECLARE_WRITE32_MEMBER(eth_remap_w); + + enum eth_remap_page_mask + { + ETH_REMAP_CHB_FLUSH = 0x00000008, + ETH_REMAP_CHB_BUF = 0x00000010, + ETH_REMAP_CHB_QUAD = 0x00000020, + ETH_REMAP_CHB_WTAG = 0x000001c0, + ETH_REMAP_CHB_RTAG = 0x00000e00, + ETH_MAP_PAGE = 0xfffff000 + }; + DECLARE_READ32_MEMBER(eth_map_page_r) { return m_eth_map_page; } + DECLARE_WRITE32_MEMBER(eth_map_page_w); + + enum eth_control_mask + { + ETH_CA = 0x00000001, + ETH_MAPEN = 0x00000002, + ETH_REMAP_CHC_BUF = 0x00000010, + ETH_REMAP_CHC_QUAD = 0x00000020, + ETH_REMAP_CHC_WTAG = 0x000001c0, + ETH_REMAP_CHC_RTAG = 0x00000e00, + ETH_BERR = 0x00001000, + ETH_MMBE = 0x00002000, + ETH_RESET = 0x00004000 + }; + DECLARE_READ32_MEMBER(eth_control_r) { return m_eth_control; } + DECLARE_WRITE32_MEMBER(eth_control_w); + DECLARE_READ32_MEMBER(timer_prescaler_r) { return m_prescaler; } DECLARE_READ32_MEMBER(timer0_r) { return m_timer_reg[0]; } DECLARE_READ32_MEMBER(timer1_r); @@ -126,7 +145,7 @@ public: ARBCTL_BGR_ETHC = 0x0001, ARBCTL_BGR_SCSI = 0x0002, ARBCTL_BGR_PLOT = 0x0004, - ARBCTL_BGR_FDC = 0x0008, + ARBCTL_BGR_FDC = 0x0008, ARBCTL_BGR_SER0 = 0x0010, ARBCTL_BGR_SER1 = 0x0020, ARBCTL_BGR_SER2 = 0x0040, @@ -186,14 +205,19 @@ public: enum dma_ctrl_mask { - DMA_CTRL_TCZERO = 0x00000001, // transfer count zero - DMA_CTRL_BERR = 0x00400000, // bus error - DMA_CTRL_BUSY = 0x02000000, // set until arbiter grants bus access + DMA_CTRL_TCZERO = 0x00000001, // transfer count zero + DMA_CTRL_TAG = 0x00000e00, // bus tag + DMA_CTRL_BERR = 0x00400000, // bus error + DMA_CTRL_ERR = 0x00800000, // checked for in scsi isr - DMA_CTRL_WRITE = 0x40000000, // indicates memory to device transfer - DMA_CTRL_FORCED = 0x60000000, + DMA_CTRL_BUSY = 0x01000000, // cleared when command complete (maybe bus grant required?) + DMA_CTRL_WAIT = 0x02000000, // waiting for bus grant + DMA_CTRL_X = 0x04000000, // set during fdc dma? - DMA_CTRL_WMASK = 0xfd000e00 // writable fields + DMA_CTRL_VIRTUAL = 0x20000000, // use virtual addressing + DMA_CTRL_WRITE = 0x40000000, // memory to device transfer + + DMA_CTRL_WMASK = 0xfd000e00 // writable fields }; DECLARE_READ32_MEMBER(dma_plotter_r) { return dma_r(space, offset, mem_mask, IOGA_DMA_PLOTTER); } DECLARE_WRITE32_MEMBER(dma_plotter_w) { dma_w(space, offset, data, mem_mask, IOGA_DMA_PLOTTER); } @@ -244,8 +268,8 @@ private: static const device_timer_id IOGA_TIMER_1 = 1; static const device_timer_id IOGA_TIMER_2 = 2; static const device_timer_id IOGA_TIMER_3 = 3; - static const device_timer_id IOGA_TIMER_DMA = 4; - static const device_timer_id IOGA_CLOCK = 5; + + static const device_timer_id IOGA_CLOCK = 4; void set_nmi_line(int state); void set_irq_line(int irq, int state); @@ -253,13 +277,21 @@ private: void write_timer(int timer, u32 value, device_timer_id id); void interrupt_clock(); - void dma_clock(int channel); + void dma_clock(); void drq(int state, int channel); devcb_write_line m_out_nmi_func; devcb_write_line m_out_irq_func; address_space *m_memory_space; + enum dma_states + { + IDLE, + WAIT, + COMMAND, + TRANSFER, + COMPLETE + }; // dma channels struct dma { @@ -268,12 +300,13 @@ private: u32 transfer_count; u32 control; - bool dma_active; - int drq_state; + dma_states state; devcb_read8 device_r; devcb_write8 device_w; const u16 arb_mask; + const int channel; + const char *name; } m_dma_channel[IOGA_DMA_CHANNELS]; u32 m_dma_plotter_eosl; @@ -302,9 +335,6 @@ private: u32 m_timer3_count; emu_timer *m_timer[4]; - // dma state - emu_timer *m_dma_timer; - u32 dma_r(address_space &space, offs_t offset, u32 mem_mask, int channel); void dma_w(address_space &space, offs_t offset, u32 data, u32 mem_mask, int channel); @@ -322,6 +352,10 @@ private: bool nmi(int state); bool irq(int state); + + u32 m_eth_remap; + u32 m_eth_map_page; + u32 m_eth_control; }; // device type definition diff --git a/src/mame/machine/interpro_sga.cpp b/src/mame/machine/interpro_sga.cpp index b33dfcce297..3d6b0731acc 100644 --- a/src/mame/machine/interpro_sga.cpp +++ b/src/mame/machine/interpro_sga.cpp @@ -105,13 +105,13 @@ WRITE32_MEMBER(interpro_sga_device::ddtc1_w) // error cycle - bit 0x10 indicates source address error (dspad1) // now expecting 0x5463? if ((m_dspad1 & 0xfffff000) == 0x40000000) - out_berr_func(space, 0x5433, m_dspad1); + out_berr_func(space, 0x5433, m_dspad1); // BINFO_SNAPOK | BINFO_BERR | BINFO_BG_ICAMMU | 0x30 | CT(3) else - out_berr_func(space, 0x5423, m_ddpad1); + out_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(1) | CT(23) + // 0x5463 = BERR|SNAPOK | BG(ICAMMU)? | TAG(40=1) | CT(23) } #endif }