From 65a381c7064936cb40a8fcbb514d2479a786d96b Mon Sep 17 00:00:00 2001 From: Patrick Mackinlay Date: Mon, 10 Jul 2017 13:40:50 +0700 Subject: interpro: serial dma [P. Mackinlay] * interpro: serial dma * implemented basic serial dma * switch to ncr53c94 * initial ethernet preparation * timer-based dma * oops (nw) --- scripts/target/mame/mess.lua | 2 - src/devices/cpu/clipper/clipperd.cpp | 24 ++-- src/mame/drivers/interpro.cpp | 40 ++++--- src/mame/includes/interpro.h | 2 +- src/mame/machine/interpro_ioga.cpp | 222 +++++++++++++++++++++++++---------- src/mame/machine/interpro_ioga.h | 86 ++++++++++++-- 6 files changed, 267 insertions(+), 109 deletions(-) diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index 3d09cca6868..d5842e9d774 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -2154,8 +2154,6 @@ files { MAME_DIR .. "src/mame/machine/cammu.cpp", MAME_DIR .. "src/mame/machine/interpro_ioga.h", MAME_DIR .. "src/mame/machine/interpro_ioga.cpp", - MAME_DIR .. "src/mame/machine/interpro_ioga.h", - MAME_DIR .. "src/mame/machine/interpro_ioga.cpp", MAME_DIR .. "src/mame/machine/interpro_mcga.h", MAME_DIR .. "src/mame/machine/interpro_mcga.cpp", MAME_DIR .. "src/mame/machine/interpro_sga.h", diff --git a/src/devices/cpu/clipper/clipperd.cpp b/src/devices/cpu/clipper/clipperd.cpp index 6d4b1a78c93..521f13d1c8d 100644 --- a/src/devices/cpu/clipper/clipperd.cpp +++ b/src/devices/cpu/clipper/clipperd.cpp @@ -72,24 +72,20 @@ static const char *const cc[] = /* * Decode an addressing mode into a string. */ -char *address (offs_t pc, u16 *insn) +std::string address (offs_t pc, u16 *insn) { - static char buffer[32]; - switch (ADDR_MODE) { - case ADDR_MODE_PC32: sprintf(buffer, "0x%x", pc + I32); break; - case ADDR_MODE_ABS32: sprintf(buffer, "0x%x", I32); break; - case ADDR_MODE_REL32: sprintf(buffer, "%d(r%d)", *(int32_t *)&insn[2], R2); break; - case ADDR_MODE_PC16: sprintf(buffer, "0x%x", pc + I16); break; - case ADDR_MODE_REL12: sprintf(buffer, "%d(r%d)", ADDR_I12, R2); break; - case ADDR_MODE_ABS16: sprintf(buffer, "0x%x", I16); break; - case ADDR_MODE_PCX: sprintf(buffer, "[r%d](pc)", ADDR_RX); break; - case ADDR_MODE_RELX: sprintf(buffer, "[r%d](r%d)", ADDR_RX, R2); break; - default: sprintf(buffer, "ERROR"); break; + case ADDR_MODE_PC32: return util::string_format("0x%x", pc + I32); + case ADDR_MODE_ABS32: return util::string_format("0x%x", I32); + case ADDR_MODE_REL32: return util::string_format("%d(r%d)", *(int32_t *)&insn[2], R2); + case ADDR_MODE_PC16: return util::string_format("0x%x", pc + I16); + case ADDR_MODE_REL12: return util::string_format("%d(r%d)", ADDR_I12, R2); + case ADDR_MODE_ABS16: return util::string_format("0x%x", I16); + case ADDR_MODE_PCX: return util::string_format("[r%d](pc)", ADDR_RX); + case ADDR_MODE_RELX: return util::string_format("[r%d](r%d)", ADDR_RX, R2); + default: return std::string("ERROR"); } - - return buffer; } /* diff --git a/src/mame/drivers/interpro.cpp b/src/mame/drivers/interpro.cpp index 1064cadbaa1..69226dfa60b 100644 --- a/src/mame/drivers/interpro.cpp +++ b/src/mame/drivers/interpro.cpp @@ -272,6 +272,7 @@ 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("scsi: read unmapped register 0x%x (%s)\n", offset >> 6, machine().describe_context()); @@ -294,6 +295,8 @@ 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("scsi: unmapped register write 0x%02x data 0x%02x (%s)\n", offset >> 6, data, machine().describe_context()); @@ -319,7 +322,7 @@ DRIVER_INIT_MEMBER(interpro_state, ip2800) static SLOT_INTERFACE_START(interpro_scsi_devices) SLOT_INTERFACE("harddisk", NSCSI_HARDDISK) SLOT_INTERFACE("cdrom", NSCSI_CDROM) - SLOT_INTERFACE_INTERNAL(INTERPRO_SCSI_ADAPTER_TAG, NCR53C90A) + SLOT_INTERFACE_INTERNAL(INTERPRO_SCSI_ADAPTER_TAG, NCR53C94) SLOT_INTERFACE_END static MACHINE_CONFIG_START(interpro_scsi_adapter) @@ -352,15 +355,18 @@ static ADDRESS_MAP_START(interpro_common_map, 0, 32, interpro_state) AM_RANGE(0x7f00031c, 0x7f00031f) AM_READWRITE16(sreg_ctrl3_r, sreg_ctrl3_w, 0xffff) AM_RANGE(0x7f000400, 0x7f00040f) AM_DEVREADWRITE8(INTERPRO_SCC1_TAG, scc85c30_device, ba_cd_inv_r, ba_cd_inv_w, 0xff) - AM_RANGE(0x7f000410, 0x7f00041f) AM_DEVREADWRITE8(INTERPRO_SCC2_TAG, scc85230_device, ba_cd_inv_r, ba_cd_inv_w, 0xff) + AM_RANGE(0x7f000410, 0x7f00041f) AM_DEVREADWRITE8(INTERPRO_SCC2_TAG, scc85c30_device, ba_cd_inv_r, ba_cd_inv_w, 0xff) AM_RANGE(0x7f000500, 0x7f0006ff) AM_READWRITE8(rtc_r, rtc_w, 0xff) AM_RANGE(0x7f000700, 0x7f00077f) AM_READ8(idprom_r, 0xff) AM_RANGE(0x7f001000, 0x7f001fff) AM_READWRITE8(scsi_r, scsi_w, 0x0000ff00) AM_RANGE(0x7f0fff00, 0x7f0fffff) AM_DEVICE(INTERPRO_IOGA_TAG, interpro_ioga_device, map) - AM_RANGE(0x08000000, 0x08000fff) AM_NOP // bogus - AM_RANGE(0x87000000, 0x8700007f) AM_READ8(slot0_r, 0xff) + // this is probably a shared memory region for the i82596 + AM_RANGE(0x08000000, 0x0800ffff) AM_RAM + + // disable the graphics slot to focus on headless operating system boot + //AM_RANGE(0x87000000, 0x8700007f) AM_READ8(slot0_r, 0xff) // 2800 (CBUS?) slots are mapped as follows AM_RANGE(0x87000000, 0x8700007f) AM_MIRROR(0x78000000) AM_READWRITE(unmapped_r, unmapped_w) @@ -416,12 +422,15 @@ static MACHINE_CONFIG_START(ip2800) MCFG_RAM_EXTRA_OPTIONS("32M,64M,128M,256M") // TODO: work out serial port assignments for mouse, console, keyboard and ? + // TODO: also work out the correct serial dma channels - scc2chanA has no dma // first serial controller and devices MCFG_SCC85C30_ADD(INTERPRO_SCC1_TAG, XTAL_4_9152MHz, 0, 0, 0, 0) MCFG_Z80SCC_OUT_TXDA_CB(DEVWRITELINE(INTERPRO_SERIAL1_TAG, rs232_port_device, write_txd)) MCFG_Z80SCC_OUT_TXDB_CB(DEVWRITELINE(INTERPRO_SERIAL2_TAG, rs232_port_device, write_txd)) MCFG_Z80SCC_OUT_INT_CB(DEVWRITELINE(INTERPRO_IOGA_TAG, interpro_ioga_device, ir11_w)) + MCFG_Z80SCC_OUT_WREQA_CB(DEVWRITELINE(INTERPRO_IOGA_TAG, interpro_ioga_device, drq_serial1)) + MCFG_Z80SCC_OUT_WREQB_CB(DEVWRITELINE(INTERPRO_IOGA_TAG, interpro_ioga_device, drq_serial2)) // is this the keyboard port? MCFG_RS232_PORT_ADD(INTERPRO_SERIAL1_TAG, default_rs232_devices, nullptr) // "keyboard" @@ -436,21 +445,22 @@ static MACHINE_CONFIG_START(ip2800) MCFG_RS232_CTS_HANDLER(DEVWRITELINE(INTERPRO_SCC1_TAG, z80scc_device, ctsb_w)) // second serial controller and devices - MCFG_SCC85230_ADD(INTERPRO_SCC2_TAG, XTAL_4_9152MHz, 0, 0, 0, 0) + MCFG_SCC85C30_ADD(INTERPRO_SCC2_TAG, XTAL_4_9152MHz, 0, 0, 0, 0) MCFG_Z80SCC_OUT_TXDA_CB(DEVWRITELINE(INTERPRO_SERIAL3_TAG, rs232_port_device, write_txd)) MCFG_Z80SCC_OUT_TXDB_CB(DEVWRITELINE(INTERPRO_SERIAL4_TAG, rs232_port_device, write_txd)) MCFG_Z80SCC_OUT_INT_CB(DEVWRITELINE(INTERPRO_IOGA_TAG, interpro_ioga_device, ir11_w)) + MCFG_Z80SCC_OUT_WREQB_CB(DEVWRITELINE(INTERPRO_IOGA_TAG, interpro_ioga_device, drq_serial0)) MCFG_RS232_PORT_ADD(INTERPRO_SERIAL3_TAG, default_rs232_devices, nullptr) - MCFG_RS232_RXD_HANDLER(DEVWRITELINE(INTERPRO_SCC1_TAG, z80scc_device, rxa_w)) - MCFG_RS232_DCD_HANDLER(DEVWRITELINE(INTERPRO_SCC1_TAG, z80scc_device, dcda_w)) - MCFG_RS232_CTS_HANDLER(DEVWRITELINE(INTERPRO_SCC1_TAG, z80scc_device, ctsa_w)) + MCFG_RS232_RXD_HANDLER(DEVWRITELINE(INTERPRO_SCC2_TAG, z80scc_device, rxa_w)) + MCFG_RS232_DCD_HANDLER(DEVWRITELINE(INTERPRO_SCC2_TAG, z80scc_device, dcda_w)) + MCFG_RS232_CTS_HANDLER(DEVWRITELINE(INTERPRO_SCC2_TAG, z80scc_device, ctsa_w)) - MCFG_RS232_PORT_ADD(INTERPRO_SERIAL4_TAG, default_rs232_devices, nullptr) //"terminal") - MCFG_RS232_RXD_HANDLER(DEVWRITELINE(INTERPRO_SCC1_TAG, z80scc_device, rxb_w)) - MCFG_RS232_DCD_HANDLER(DEVWRITELINE(INTERPRO_SCC1_TAG, z80scc_device, dcdb_w)) - MCFG_RS232_CTS_HANDLER(DEVWRITELINE(INTERPRO_SCC1_TAG, z80scc_device, ctsb_w)) + MCFG_RS232_PORT_ADD(INTERPRO_SERIAL4_TAG, default_rs232_devices, nullptr) + MCFG_RS232_RXD_HANDLER(DEVWRITELINE(INTERPRO_SCC2_TAG, z80scc_device, rxb_w)) + MCFG_RS232_DCD_HANDLER(DEVWRITELINE(INTERPRO_SCC2_TAG, z80scc_device, dcdb_w)) + MCFG_RS232_CTS_HANDLER(DEVWRITELINE(INTERPRO_SCC2_TAG, z80scc_device, ctsb_w)) // real-time clock/non-volatile memory MCFG_MC146818_ADD(INTERPRO_RTC_TAG, XTAL_32_768kHz) @@ -483,9 +493,11 @@ 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) - 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_SCSI, DEVREAD8(INTERPRO_SCSI_DEVICE_TAG, ncr53c94_device, mdma_r), DEVWRITE8(INTERPRO_SCSI_DEVICE_TAG, ncr53c94_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_DMA_SERIAL_CB(IOGA_DMA_SERIAL0, DEVREAD8(INTERPRO_SCC2_TAG, z80scc_device, db_r), DEVWRITE8(INTERPRO_SCC2_TAG, z80scc_device, db_w)) + MCFG_INTERPRO_IOGA_DMA_SERIAL_CB(IOGA_DMA_SERIAL1, DEVREAD8(INTERPRO_SCC2_TAG, z80scc_device, da_r), DEVWRITE8(INTERPRO_SCC2_TAG, z80scc_device, da_w)) + MCFG_INTERPRO_IOGA_DMA_SERIAL_CB(IOGA_DMA_SERIAL2, DEVREAD8(INTERPRO_SCC1_TAG, z80scc_device, db_r), DEVWRITE8(INTERPRO_SCC1_TAG, z80scc_device, db_w)) MCFG_INTERPRO_IOGA_FDCTC_CB(DEVWRITELINE(INTERPRO_FDC_TAG, n82077aa_device, tc_line_w)) MCFG_INTERPRO_IOGA_DMA_BUS(INTERPRO_CAMMU_TAG, 0) diff --git a/src/mame/includes/interpro.h b/src/mame/includes/interpro.h index 543cb147285..d2a08a9d47d 100644 --- a/src/mame/includes/interpro.h +++ b/src/mame/includes/interpro.h @@ -83,7 +83,7 @@ public: required_device m_rtc; required_device m_fdc; required_device m_scsibus; - required_device m_scsi; + required_device m_scsi; required_device m_ioga; required_device m_mcga; required_device m_sga; diff --git a/src/mame/machine/interpro_ioga.cpp b/src/mame/machine/interpro_ioga.cpp index 4e7856c3d2e..e3e4c921324 100644 --- a/src/mame/machine/interpro_ioga.cpp +++ b/src/mame/machine/interpro_ioga.cpp @@ -25,6 +25,7 @@ #define LOG_HWINT_ENABLE 0 #define LOG_DMA_ENABLE 0 #define LOG_TIMER_ENABLE 0 +#define LOG_DMA_SERIAL_ENABLE 0 #define VERBOSE 0 @@ -33,12 +34,14 @@ #define LOG_TIMER(timer, ...) if (LOG_TIMER_ENABLE & (1 << timer)) logerror(__VA_ARGS__) #define LOG_HWINT(interrupt, ...) if (LOG_HWINT_ENABLE & (1 << interrupt)) logerror(__VA_ARGS__) #define LOG_DMA(channel, ...) if (LOG_DMA_ENABLE & (1 << channel)) logerror(__VA_ARGS__) +#define LOG_DMA_SERIAL(channel, ...) if (LOG_DMA_SERIAL_ENABLE & (1 << channel)) logerror(__VA_ARGS__) #define LOG_ETH(...) logerror(__VA_ARGS__) #else #define LOG_INTERRUPT(...) #define LOG_TIMER(timer, ...) #define LOG_HWINT(interrupt, ...) #define LOG_DMA(channel, ...) +#define LOG_DMA_SERIAL(channel, ...) #define LOG_ETH(...) #endif @@ -51,7 +54,18 @@ DEVICE_ADDRESS_MAP_START(map, 32, interpro_ioga_device) AM_RANGE(0x1c, 0x1f) AM_READWRITE(dma_plotter_eosl_r, dma_plotter_eosl_w) AM_RANGE(0x20, 0x2f) AM_READWRITE(dma_scsi_r, dma_scsi_w) AM_RANGE(0x30, 0x3f) AM_READWRITE(dma_floppy_r, dma_floppy_w) - AM_RANGE(0x40, 0x57) AM_READWRITE(dma_serial_r, dma_serial_w) + + AM_RANGE(0x40, 0x43) AM_READWRITE(dma_serial0_addr_r, dma_serial0_addr_w) + AM_RANGE(0x44, 0x47) AM_READWRITE16(dma_serial0_count_r, dma_serial0_count_w, 0x0000ffff) + AM_RANGE(0x44, 0x47) AM_READWRITE16(dma_serial0_ctrl_r, dma_serial0_ctrl_w, 0xffff0000) + + AM_RANGE(0x48, 0x4b) AM_READWRITE(dma_serial1_addr_r, dma_serial1_addr_w) + AM_RANGE(0x4c, 0x4f) AM_READWRITE16(dma_serial1_count_r, dma_serial1_count_w, 0x0000ffff) + AM_RANGE(0x4c, 0x4f) AM_READWRITE16(dma_serial1_ctrl_r, dma_serial1_ctrl_w, 0xffff0000) + + AM_RANGE(0x50, 0x53) AM_READWRITE(dma_serial2_addr_r, dma_serial2_addr_w) + AM_RANGE(0x54, 0x57) AM_READWRITE16(dma_serial2_count_r, dma_serial2_count_w, 0x0000ffff) + AM_RANGE(0x54, 0x57) AM_READWRITE16(dma_serial2_ctrl_r, dma_serial2_ctrl_w, 0xffff0000) AM_RANGE(0x5c, 0x7f) AM_READWRITE16(icr_r, icr_w, 0xffffffff) AM_RANGE(0x80, 0x83) AM_READWRITE16(icr18_r, icr18_w, 0x0000ffff) @@ -79,11 +93,15 @@ interpro_ioga_device::interpro_ioga_device(const machine_config &mconfig, const m_out_irq_func(*this), m_memory_space(nullptr), m_dma_channel{ - { 0,0,0,0,IDLE, {*this}, {*this}, ARBCTL_BGR_PLOT, IOGA_DMA_PLOTTER, "plotter" }, - { 0,0,0,0,IDLE, {*this}, {*this}, ARBCTL_BGR_SCSI, IOGA_DMA_SCSI, "scsi" }, - { 0,0,0,0,IDLE, {*this}, {*this}, ARBCTL_BGR_FDC, IOGA_DMA_FLOPPY, "floppy" }, - { 0,0,0,0,IDLE, {*this}, {*this}, ARBCTL_BGR_SER0 | ARBCTL_BGR_SER1 | ARBCTL_BGR_SER2, IOGA_DMA_SERIAL, "serial" } }, - m_fdc_tc_func(*this) + { 0,0,0,0,0,IDLE, {*this}, {*this}, ARBCTL_BGR_PLOT, IOGA_DMA_PLOTTER, "plotter" }, + { 0,0,0,0,0,IDLE, {*this}, {*this}, ARBCTL_BGR_SCSI, IOGA_DMA_SCSI, "scsi" }, + { 0,0,0,0,0,IDLE, {*this}, {*this}, ARBCTL_BGR_FDC, IOGA_DMA_FLOPPY, "floppy" } }, + m_dma_serial_channel { + { 0,0,0,0,IDLE, {*this}, {*this}, ARBCTL_BGR_SER0, IOGA_DMA_SERIAL0, "serial0" }, + { 0,0,0,0,IDLE, {*this}, {*this}, ARBCTL_BGR_SER1, IOGA_DMA_SERIAL1, "serial1" }, + { 0,0,0,0,IDLE, {*this}, {*this}, ARBCTL_BGR_SER2, IOGA_DMA_SERIAL2, "serial2" } }, + m_fdc_tc_func(*this), + m_eth_ca_func(*this) { } @@ -127,13 +145,20 @@ void interpro_ioga_device::device_start() siblingdevice("mmu")->interface(mmu); m_memory_space = &mmu->space(0); - for (int i = 0; i < IOGA_DMA_CHANNELS; i++) + for (auto &dma_channel : m_dma_channel) + { + dma_channel.device_r.resolve_safe(0xff); + dma_channel.device_w.resolve(); + } + + for (auto &dma_channel : m_dma_serial_channel) { - m_dma_channel[i].device_r.resolve_safe(0xff); - m_dma_channel[i].device_w.resolve(); + dma_channel.device_r.resolve_safe(0xff); + dma_channel.device_w.resolve(); } m_fdc_tc_func.resolve(); + m_eth_ca_func.resolve(); // allocate ioga timers m_timer[0] = timer_alloc(IOGA_TIMER_0); @@ -291,6 +316,7 @@ void interpro_ioga_device::device_timer(emu_timer &timer, device_timer_id id, in case IOGA_CLOCK: interrupt_clock(); dma_clock(); + dma_serial_clock(); break; } } @@ -646,11 +672,10 @@ void interpro_ioga_device::dma_clock() case COMMAND: // start a command - // HACK: busy flag indicates bus access required? - if (dma_channel.control & DMA_CTRL_BUSY) + if (dma_channel.control & DMA_CTRL_BGR) dma_channel.state = WAIT; else - dma_channel.state = COMPLETE; + dma_channel.state = FINAL; break; case WAIT: @@ -672,25 +697,26 @@ void interpro_ioga_device::dma_clock() break; case TRANSFER: - // if there are no more bytes remaining, terminate the transfer - if (dma_channel.transfer_count == 0) + if (dma_channel.transfer_count) { - 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) + if (dma_channel.drq_state) { - LOG_DMA(dma_channel.channel, "dma: asserting fdc terminal count line\n"); - - m_fdc_tc_func(ASSERT_LINE); - m_fdc_tc_func(CLEAR_LINE); + // transfer from the memory to device or device to memory + // TODO: implement virtual addressing when DMA_CTRL_VIRTUAL is set + + 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--; } - - // set transfer count zero flag - dma_channel.control |= DMA_CTRL_TCZERO; - dma_channel.state = COMPLETE; } + else + dma_channel.state = COMPLETE; #if IOGA_DMA_DIAG_HACK else #define TAG ((dma_channel.control & DMA_CTRL_TAG) >> 3) @@ -761,40 +787,113 @@ void interpro_ioga_device::dma_clock() break; case COMPLETE: - // clear busy flag - dma_channel.control &= ~DMA_CTRL_BUSY; + 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); + } + + // clear bus grant required + dma_channel.control &= ~DMA_CTRL_BGR; + + // set transfer count zero flag + dma_channel.control |= DMA_CTRL_TCZERO; + + dma_channel.state = FINAL; + break; + + case FINAL: dma_channel.state = IDLE; break; } } } -void interpro_ioga_device::drq(int state, int channel) +void interpro_ioga_device::dma_serial_clock() { - // TODO: implement virtual addressing when DMA_CTRL_VIRTUAL is set + for (auto &dma_channel : m_dma_serial_channel) + { + switch (dma_channel.state) + { + case IDLE: + if (dma_channel.drq_state && dma_channel.count) + dma_channel.state = WAIT; + break; - struct dma &dma_channel = m_dma_channel[channel]; + case COMMAND: + case WAIT: + if (m_arbctl & dma_channel.arb_mask) + dma_channel.state = TRANSFER; + break; - if (state) - { - LOG_DMA(channel, "dma: drq for channel %d asserted\n", channel); + case TRANSFER: + if (dma_channel.count) + { + if (dma_channel.drq_state) + { + // transfer from the memory to device or device to memory + // TODO: work out which control register bits indicate read from device + if (true) + { + u8 data = m_memory_space->read_byte(dma_channel.address); - 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)); + LOG_DMA_SERIAL(dma_channel.channel, "dma: transferring byte 0x%02x to serial channel %d\n", data, dma_channel.channel); + + dma_channel.device_w(data); + } + else + m_memory_space->write_byte(dma_channel.address, dma_channel.device_r()); + + // increment address and decrement count + dma_channel.address++; + dma_channel.count--; + } + } else - m_memory_space->write_byte(dma_channel.real_address, dma_channel.device_r()); + dma_channel.state = COMPLETE; + break; + + case COMPLETE: + // transfer count zero + dma_channel.control |= 0x20; + + dma_channel.state = FINAL; + break; - // increment addresses and decrement count - dma_channel.real_address++; - dma_channel.virtual_address++; - dma_channel.transfer_count--; + case FINAL: + // raise an interrupt + m_hwicr[16] |= IOGA_INTERRUPT_PENDING; + + dma_channel.state = IDLE; + break; } } - else - LOG_DMA(channel, "dma: drq for channel %d deasserted\n", channel); +} + +void interpro_ioga_device::drq(int state, int channel) +{ + struct dma &dma_channel = m_dma_channel[channel]; + + dma_channel.drq_state = state; + + // only log every 256 bytes + if ((dma_channel.transfer_count & 0xff) == 0) + LOG_DMA(channel, "dma: drq for channel %d %s, transfer_count 0x%08x\n", channel, state ? "asserted" : "deasserted", dma_channel.transfer_count); +} + +void interpro_ioga_device::drq_serial(int state, int channel) +{ + struct dma_serial &dma_channel = m_dma_serial_channel[channel]; + + dma_channel.drq_state = state; + + LOG_DMA_SERIAL(channel, "dma: drq for serial channel %d %s, counter 0x%04x\n", channel, state ? "asserted" : "deasserted", dma_channel.count); } u32 interpro_ioga_device::dma_r(address_space &space, offs_t offset, u32 mem_mask, int channel) @@ -856,32 +955,25 @@ void interpro_ioga_device::dma_w(address_space &space, offs_t offset, u32 data, } } -u32 interpro_ioga_device::dma_serial_r(address_space &space, offs_t offset, u32 mem_mask) +void interpro_ioga_device::dma_serial_addr_w(address_space &space, offs_t offset, u32 data, u32 mem_mask, int channel) { - int channel = offset >> 1; + LOG_DMA_SERIAL(channel, "dma: serial channel %d address = 0x%08x (%s)\n", channel, data, machine().describe_context()); - if (offset & 1) - return m_dma_serial[channel].control; - else - return m_dma_serial[channel].address; + m_dma_serial_channel[channel].address = data; } -void interpro_ioga_device::dma_serial_w(address_space &space, offs_t offset, u32 data, u32 mem_mask) +void interpro_ioga_device::dma_serial_count_w(address_space &space, offs_t offset, u16 data, u16 mem_mask, int channel) { - int channel = offset >> 1; + LOG_DMA_SERIAL(channel, "dma: serial channel %d count = 0x%04x (%s)\n", channel, data, machine().describe_context()); - if (offset & 1) - { - LOG_DMA(IOGA_DMA_SERIAL, "dma: channel %d(%d) control = 0x%08x, mask = 0x%08x (%s)\n", IOGA_DMA_SERIAL, channel, data, mem_mask, machine().describe_context()); + m_dma_serial_channel[channel].count = data; +} - m_dma_serial[channel].control = (m_dma_serial[channel].control & ~mem_mask) | data; - } - else - { - LOG_DMA(IOGA_DMA_SERIAL, "dma: channel %d(%d) address = 0x%08x, mask = 0x%08x (%s)\n", IOGA_DMA_SERIAL, channel, data, mem_mask, machine().describe_context()); +void interpro_ioga_device::dma_serial_ctrl_w(address_space &space, offs_t offset, u16 data, u16 mem_mask, int channel) +{ + LOG_DMA_SERIAL(channel, "dma: serial channel %d control = 0x%04x (%s)\n", channel, data, machine().describe_context()); - m_dma_serial[channel].address = (m_dma_serial[channel].address & ~mem_mask) | data; - } + m_dma_serial_channel[channel].control = data; } READ32_MEMBER(interpro_ioga_device::error_businfo_r) diff --git a/src/mame/machine/interpro_ioga.h b/src/mame/machine/interpro_ioga.h index 94e282a9e2c..530790cb3e0 100644 --- a/src/mame/machine/interpro_ioga.h +++ b/src/mame/machine/interpro_ioga.h @@ -19,9 +19,16 @@ devcb = &interpro_ioga_device::static_set_dma_r_callback(*device, _channel, DEVCB_##_dma_r); \ devcb = &interpro_ioga_device::static_set_dma_w_callback(*device, _channel, DEVCB_##_dma_w); +#define MCFG_INTERPRO_IOGA_DMA_SERIAL_CB(_channel, _dma_r, _dma_w) \ + devcb = &interpro_ioga_device::static_set_dma_serial_r_callback(*device, _channel, DEVCB_##_dma_r); \ + devcb = &interpro_ioga_device::static_set_dma_serial_w_callback(*device, _channel, DEVCB_##_dma_w); + #define MCFG_INTERPRO_IOGA_FDCTC_CB(_tc) \ devcb = &interpro_ioga_device::static_set_fdc_tc_callback(*device, DEVCB_##_tc); +#define MCFG_INTERPRO_IOGA_ETH_CA_CB(_ca) \ + devcb = &interpro_ioga_device::static_set_eth_ca_callback(*device, DEVCB_##_ca); + #define MCFG_INTERPRO_IOGA_DMA_BUS(_mmu, _space) // timer 0 seem to be a 60Hz cycle @@ -54,11 +61,15 @@ #define IOGA_INTERRUPT_SOFT_LO 4 #define IOGA_INTERRUPT_SOFT_HI 5 -#define IOGA_DMA_CHANNELS 4 -#define IOGA_DMA_PLOTTER 0 -#define IOGA_DMA_SCSI 1 -#define IOGA_DMA_FLOPPY 2 -#define IOGA_DMA_SERIAL 3 +#define IOGA_DMA_CHANNELS 3 +#define IOGA_DMA_PLOTTER 0 +#define IOGA_DMA_SCSI 1 +#define IOGA_DMA_FLOPPY 2 + +#define IOGA_DMA_SERIAL_CHANNELS 3 +#define IOGA_DMA_SERIAL0 0 +#define IOGA_DMA_SERIAL1 1 +#define IOGA_DMA_SERIAL2 2 class interpro_ioga_device : public device_t { @@ -71,7 +82,11 @@ public: template static devcb_base &static_set_dma_r_callback(device_t &device, int channel, _Object object) { return downcast(device).m_dma_channel[channel].device_r.set_callback(object); } template static devcb_base &static_set_dma_w_callback(device_t &device, int channel, _Object object) { return downcast(device).m_dma_channel[channel].device_w.set_callback(object); } + template static devcb_base &static_set_dma_serial_r_callback(device_t &device, int channel, _Object object) { return downcast(device).m_dma_serial_channel[channel].device_r.set_callback(object); } + template static devcb_base &static_set_dma_serial_w_callback(device_t &device, int channel, _Object object) { return downcast(device).m_dma_serial_channel[channel].device_w.set_callback(object); } + template static devcb_base &static_set_fdc_tc_callback(device_t &device, _Object object) { return downcast(device).m_fdc_tc_func.set_callback(object); } + template static devcb_base &static_set_eth_ca_callback(device_t &device, _Object object) { return downcast(device).m_eth_ca_func.set_callback(object); } virtual DECLARE_ADDRESS_MAP(map, 32); @@ -97,6 +112,10 @@ public: DECLARE_WRITE_LINE_MEMBER(drq_scsi) { drq(state, IOGA_DMA_SCSI); } DECLARE_WRITE_LINE_MEMBER(drq_floppy) { drq(state, IOGA_DMA_FLOPPY); } + DECLARE_WRITE_LINE_MEMBER(drq_serial0) { drq_serial(state, IOGA_DMA_SERIAL0); } + DECLARE_WRITE_LINE_MEMBER(drq_serial1) { drq_serial(state, IOGA_DMA_SERIAL1); } + DECLARE_WRITE_LINE_MEMBER(drq_serial2) { drq_serial(state, IOGA_DMA_SERIAL2); } + enum eth_remap_mask { ETH_REMAP_CHA_FLUSH = 0x00000008, @@ -123,7 +142,7 @@ public: enum eth_control_mask { - ETH_CA = 0x00000001, + ETH_CA = 0x00000001, // channel attention ETH_MAPEN = 0x00000002, ETH_REMAP_CHC_BUF = 0x00000010, ETH_REMAP_CHC_QUAD = 0x00000020, @@ -210,7 +229,7 @@ public: DMA_CTRL_BERR = 0x00400000, // bus error DMA_CTRL_ERR = 0x00800000, // checked for in scsi isr - DMA_CTRL_BUSY = 0x01000000, // cleared when command complete (maybe bus grant required?) + DMA_CTRL_BGR = 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? @@ -226,8 +245,26 @@ public: DECLARE_READ32_MEMBER(dma_floppy_r) { return dma_r(space, offset, mem_mask, IOGA_DMA_FLOPPY); } DECLARE_WRITE32_MEMBER(dma_floppy_w) { dma_w(space, offset, data, mem_mask, IOGA_DMA_FLOPPY); } - DECLARE_READ32_MEMBER(dma_serial_r); - DECLARE_WRITE32_MEMBER(dma_serial_w); + DECLARE_READ32_MEMBER(dma_serial0_addr_r) { return dma_serial_addr_r(space, offset, mem_mask, IOGA_DMA_SERIAL0); } + DECLARE_WRITE32_MEMBER(dma_serial0_addr_w) { dma_serial_addr_w(space, offset, data, mem_mask, IOGA_DMA_SERIAL0); } + DECLARE_READ16_MEMBER(dma_serial0_count_r) { return dma_serial_count_r(space, offset, mem_mask, IOGA_DMA_SERIAL0); } + DECLARE_WRITE16_MEMBER(dma_serial0_count_w) { dma_serial_count_w(space, offset, data, mem_mask, IOGA_DMA_SERIAL0); } + DECLARE_READ16_MEMBER(dma_serial0_ctrl_r) { return dma_serial_ctrl_r(space, offset, mem_mask, IOGA_DMA_SERIAL0); } + DECLARE_WRITE16_MEMBER(dma_serial0_ctrl_w) { dma_serial_ctrl_w(space, offset, data, mem_mask, IOGA_DMA_SERIAL0); } + + DECLARE_READ32_MEMBER(dma_serial1_addr_r) { return dma_serial_addr_r(space, offset, mem_mask, IOGA_DMA_SERIAL1); } + DECLARE_WRITE32_MEMBER(dma_serial1_addr_w) { dma_serial_addr_w(space, offset, data, mem_mask, IOGA_DMA_SERIAL1); } + DECLARE_READ16_MEMBER(dma_serial1_count_r) { return dma_serial_count_r(space, offset, mem_mask, IOGA_DMA_SERIAL1); } + DECLARE_WRITE16_MEMBER(dma_serial1_count_w) { dma_serial_count_w(space, offset, data, mem_mask, IOGA_DMA_SERIAL1); } + DECLARE_READ16_MEMBER(dma_serial1_ctrl_r) { return dma_serial_ctrl_r(space, offset, mem_mask, IOGA_DMA_SERIAL1); } + DECLARE_WRITE16_MEMBER(dma_serial1_ctrl_w) { dma_serial_ctrl_w(space, offset, data, mem_mask, IOGA_DMA_SERIAL1); } + + DECLARE_READ32_MEMBER(dma_serial2_addr_r) { return dma_serial_addr_r(space, offset, mem_mask, IOGA_DMA_SERIAL2); } + DECLARE_WRITE32_MEMBER(dma_serial2_addr_w) { dma_serial_addr_w(space, offset, data, mem_mask, IOGA_DMA_SERIAL2); } + DECLARE_READ16_MEMBER(dma_serial2_count_r) { return dma_serial_count_r(space, offset, mem_mask, IOGA_DMA_SERIAL2); } + DECLARE_WRITE16_MEMBER(dma_serial2_count_w) { dma_serial_count_w(space, offset, data, mem_mask, IOGA_DMA_SERIAL2); } + DECLARE_READ16_MEMBER(dma_serial2_ctrl_r) { return dma_serial_ctrl_r(space, offset, mem_mask, IOGA_DMA_SERIAL2); } + DECLARE_WRITE16_MEMBER(dma_serial2_ctrl_w) { dma_serial_ctrl_w(space, offset, data, mem_mask, IOGA_DMA_SERIAL2); } DECLARE_READ32_MEMBER(dma_plotter_eosl_r) { return m_dma_plotter_eosl; } DECLARE_WRITE32_MEMBER(dma_plotter_eosl_w) { m_dma_plotter_eosl = data; } @@ -278,8 +315,10 @@ private: void interrupt_clock(); void dma_clock(); + void dma_serial_clock(); void drq(int state, int channel); + void drq_serial(int state, int channel); devcb_write_line m_out_nmi_func; devcb_write_line m_out_irq_func; address_space *m_memory_space; @@ -290,7 +329,8 @@ private: WAIT, COMMAND, TRANSFER, - COMPLETE + COMPLETE, + FINAL }; // dma channels struct dma @@ -300,6 +340,7 @@ private: u32 transfer_count; u32 control; + int drq_state; dma_states state; devcb_read8 device_r; devcb_write8 device_w; @@ -310,13 +351,25 @@ private: } m_dma_channel[IOGA_DMA_CHANNELS]; u32 m_dma_plotter_eosl; - struct serial_dma + // dma serial channels + struct dma_serial { u32 address; - u32 control; - } m_dma_serial[3]; + u16 count; + u16 control; + + 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_serial_channel[IOGA_DMA_SERIAL_CHANNELS]; devcb_write_line m_fdc_tc_func; + devcb_write_line m_eth_ca_func; u32 m_active_interrupt_type; u32 m_active_interrupt_number; @@ -338,6 +391,13 @@ private: 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); + u32 dma_serial_addr_r(address_space &space, offs_t offset, u32 mem_mask, int channel) { return m_dma_serial_channel[channel].address; } + void dma_serial_addr_w(address_space &space, offs_t offset, u32 data, u32 mem_mask, int channel); + u16 dma_serial_count_r(address_space &space, offs_t offset, u16 mem_mask, int channel) { return m_dma_serial_channel[channel].count; } + void dma_serial_count_w(address_space &space, offs_t offset, u16 data, u16 mem_mask, int channel); + u16 dma_serial_ctrl_r(address_space &space, offs_t offset, u16 mem_mask, int channel) { return m_dma_serial_channel[channel].control; } + void dma_serial_ctrl_w(address_space &space, offs_t offset, u16 data, u16 mem_mask, int channel); + u16 m_arbctl; u32 m_error_address; -- cgit v1.2.3