mirror of
https://github.com/holub/mame
synced 2025-04-23 00:39:36 +03:00
interpro: serial dma [P. Mackinlay]
* interpro: serial dma * implemented basic serial dma * switch to ncr53c94 * initial ethernet preparation * timer-based dma * oops (nw)
This commit is contained in:
parent
5ddd006919
commit
65a381c706
@ -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",
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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)
|
||||
|
||||
|
@ -83,7 +83,7 @@ public:
|
||||
required_device<mc146818_device> m_rtc;
|
||||
required_device<n82077aa_device> m_fdc;
|
||||
required_device<nscsi_bus_device> m_scsibus;
|
||||
required_device<ncr53c90a_device> m_scsi;
|
||||
required_device<ncr53c94_device> m_scsi;
|
||||
required_device<interpro_ioga_device> m_ioga;
|
||||
required_device<interpro_fmcc_device> m_mcga;
|
||||
required_device<interpro_sga_device> m_sga;
|
||||
|
@ -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)
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
for (auto &dma_channel : m_dma_serial_channel)
|
||||
{
|
||||
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");
|
||||
// transfer from the memory to device or device to memory
|
||||
// TODO: implement virtual addressing when DMA_CTRL_VIRTUAL is set
|
||||
|
||||
m_fdc_tc_func(ASSERT_LINE);
|
||||
m_fdc_tc_func(CLEAR_LINE);
|
||||
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,8 +787,89 @@ 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::dma_serial_clock()
|
||||
{
|
||||
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;
|
||||
|
||||
case COMMAND:
|
||||
case WAIT:
|
||||
if (m_arbctl & dma_channel.arb_mask)
|
||||
dma_channel.state = TRANSFER;
|
||||
break;
|
||||
|
||||
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);
|
||||
|
||||
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
|
||||
dma_channel.state = COMPLETE;
|
||||
break;
|
||||
|
||||
case COMPLETE:
|
||||
// transfer count zero
|
||||
dma_channel.control |= 0x20;
|
||||
|
||||
dma_channel.state = FINAL;
|
||||
break;
|
||||
|
||||
case FINAL:
|
||||
// raise an interrupt
|
||||
m_hwicr[16] |= IOGA_INTERRUPT_PENDING;
|
||||
|
||||
dma_channel.state = IDLE;
|
||||
break;
|
||||
}
|
||||
@ -771,30 +878,22 @@ void interpro_ioga_device::dma_clock()
|
||||
|
||||
void interpro_ioga_device::drq(int state, int channel)
|
||||
{
|
||||
// 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);
|
||||
dma_channel.drq_state = state;
|
||||
|
||||
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());
|
||||
// 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);
|
||||
}
|
||||
|
||||
// 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);
|
||||
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)
|
||||
|
@ -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<class _Object> static devcb_base &static_set_dma_r_callback(device_t &device, int channel, _Object object) { return downcast<interpro_ioga_device &>(device).m_dma_channel[channel].device_r.set_callback(object); }
|
||||
template<class _Object> static devcb_base &static_set_dma_w_callback(device_t &device, int channel, _Object object) { return downcast<interpro_ioga_device &>(device).m_dma_channel[channel].device_w.set_callback(object); }
|
||||
|
||||
template<class _Object> static devcb_base &static_set_dma_serial_r_callback(device_t &device, int channel, _Object object) { return downcast<interpro_ioga_device &>(device).m_dma_serial_channel[channel].device_r.set_callback(object); }
|
||||
template<class _Object> static devcb_base &static_set_dma_serial_w_callback(device_t &device, int channel, _Object object) { return downcast<interpro_ioga_device &>(device).m_dma_serial_channel[channel].device_w.set_callback(object); }
|
||||
|
||||
template<class _Object> static devcb_base &static_set_fdc_tc_callback(device_t &device, _Object object) { return downcast<interpro_ioga_device &>(device).m_fdc_tc_func.set_callback(object); }
|
||||
template<class _Object> static devcb_base &static_set_eth_ca_callback(device_t &device, _Object object) { return downcast<interpro_ioga_device &>(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;
|
||||
|
Loading…
Reference in New Issue
Block a user