summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author AJR <ajrhacker@users.noreply.github.com>2021-05-08 13:01:38 -0400
committer AJR <ajrhacker@users.noreply.github.com>2021-05-08 13:02:41 -0400
commit7ed1de96c98facd20f49ab7122f66b24884ebe4d (patch)
tree0601096faeba824a1ba518ffb1925b2a740f739c
parent173a0cf3b6d5dd7d8b3fd06da9c1f332bdf7f83f (diff)
mac.cpp, mac128.cpp, macprtb.cpp, macpwrbk030.cpp, macquadra.cpp: Add helper device to permit use of "new" SCSI bus and 53(C)80 emulation with macse and later
-rw-r--r--scripts/target/mame/mess.lua2
-rw-r--r--src/devices/bus/nscsi/devices.cpp8
-rw-r--r--src/devices/bus/nscsi/devices.h1
-rw-r--r--src/mame/drivers/mac.cpp40
-rw-r--r--src/mame/drivers/mac128.cpp63
-rw-r--r--src/mame/drivers/macprtb.cpp100
-rw-r--r--src/mame/drivers/macpwrbk030.cpp113
-rw-r--r--src/mame/drivers/macquadra700.cpp9
-rw-r--r--src/mame/includes/mac.h11
-rw-r--r--src/mame/machine/mac.cpp46
-rw-r--r--src/mame/machine/macscsi.cpp318
-rw-r--r--src/mame/machine/macscsi.h70
12 files changed, 613 insertions, 168 deletions
diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua
index 07d5f494dc3..b40f73b2c46 100644
--- a/scripts/target/mame/mess.lua
+++ b/scripts/target/mame/mess.lua
@@ -1816,6 +1816,8 @@ files {
MAME_DIR .. "src/mame/machine/macpci.cpp",
MAME_DIR .. "src/mame/machine/cuda.cpp",
MAME_DIR .. "src/mame/machine/cuda.h",
+ MAME_DIR .. "src/mame/machine/macscsi.cpp",
+ MAME_DIR .. "src/mame/machine/macscsi.h",
MAME_DIR .. "src/mame/drivers/iphone2g.cpp",
MAME_DIR .. "src/mame/drivers/superga2.cpp",
}
diff --git a/src/devices/bus/nscsi/devices.cpp b/src/devices/bus/nscsi/devices.cpp
index 9591d9d1b38..7a422c648f2 100644
--- a/src/devices/bus/nscsi/devices.cpp
+++ b/src/devices/bus/nscsi/devices.cpp
@@ -29,4 +29,10 @@ void default_scsi_devices(device_slot_interface &device)
device.option_add("cdu561_25", CDU561_25);
device.option_add("smoc501", SMOC501);
device.option_add("aplcd150", APPLECD150);
-};
+}
+
+void mac_scsi_devices(device_slot_interface &device)
+{
+ device.option_add("harddisk", NSCSI_HARDDISK);
+ device.option_add("cdrom", NSCSI_CDROM_APPLE);
+}
diff --git a/src/devices/bus/nscsi/devices.h b/src/devices/bus/nscsi/devices.h
index 9958577517a..996fbd1b77e 100644
--- a/src/devices/bus/nscsi/devices.h
+++ b/src/devices/bus/nscsi/devices.h
@@ -7,5 +7,6 @@
#pragma once
extern void default_scsi_devices(device_slot_interface &device);
+extern void mac_scsi_devices(device_slot_interface &device);
#endif // MAME_BUS_NSCSI_DEVICES_H
diff --git a/src/mame/drivers/mac.cpp b/src/mame/drivers/mac.cpp
index 8d9dbfa9310..55e1ed9b47e 100644
--- a/src/mame/drivers/mac.cpp
+++ b/src/mame/drivers/mac.cpp
@@ -20,9 +20,7 @@
#include "machine/iwm.h"
#include "machine/swim1.h"
#include "machine/swim2.h"
-#include "bus/scsi/scsi.h"
-#include "bus/scsi/scsihd.h"
-#include "bus/scsi/scsicd.h"
+#include "bus/nscsi/devices.h"
// NuBus and 030/040 PDS cards
#include "bus/nubus/nubus_48gc.h"
@@ -50,9 +48,9 @@
#include "speaker.h"
#include "mac.lh"
-#define C7M (7833600)
-#define C15M (C7M*2)
-#define C32M (C15M*2)
+#define C32M (31.3344_MHz_XTAL)
+#define C15M (C32M/2)
+#define C7M (C32M/4)
// do this here - screen_update is called each scanline when stepping in the
// debugger, which means you can't escape the VIA2 IRQ handler
@@ -637,15 +635,27 @@ void mac_state::add_base_devices(machine_config &config, bool rtc, int woz_versi
void mac_state::add_scsi(machine_config &config, bool cdrom)
{
- scsi_port_device &scsibus(SCSI_PORT(config, "scsi"));
- scsibus.set_slot_device(1, "harddisk", SCSIHD, DEVICE_INPUT_DEFAULTS_NAME(SCSI_ID_6));
- scsibus.set_slot_device(2, "harddisk", SCSIHD, DEVICE_INPUT_DEFAULTS_NAME(SCSI_ID_5));
- if (cdrom)
- scsibus.set_slot_device(3, "cdrom", SCSICD, DEVICE_INPUT_DEFAULTS_NAME(SCSI_ID_4));
-
- NCR5380(config, m_ncr5380, C7M);
- m_ncr5380->set_scsi_port("scsi");
- m_ncr5380->irq_callback().set(FUNC(mac_state::mac_scsi_irq));
+ NSCSI_BUS(config, "scsi");
+ NSCSI_CONNECTOR(config, "scsi:0", mac_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:1", mac_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:2", mac_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:3", mac_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:4", mac_scsi_devices, cdrom ? "cdrom" : nullptr);
+ NSCSI_CONNECTOR(config, "scsi:5", mac_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:6", mac_scsi_devices, "harddisk");
+ NSCSI_CONNECTOR(config, "scsi:7").option_set("ncr5380", NCR53C80).machine_config([this](device_t *device) {
+ ncr53c80_device &adapter = downcast<ncr53c80_device &>(*device);
+ adapter.irq_handler().set(*this, FUNC(mac_state::mac_scsi_irq));
+ adapter.drq_handler().set(m_scsihelp, FUNC(mac_scsi_helper_device::drq_w));
+ });
+
+ MAC_SCSI_HELPER(config, m_scsihelp);
+ m_scsihelp->scsi_read_callback().set(m_ncr5380, FUNC(ncr53c80_device::read));
+ m_scsihelp->scsi_write_callback().set(m_ncr5380, FUNC(ncr53c80_device::write));
+ m_scsihelp->scsi_dma_read_callback().set(m_ncr5380, FUNC(ncr53c80_device::dma_r));
+ m_scsihelp->scsi_dma_write_callback().set(m_ncr5380, FUNC(ncr53c80_device::dma_w));
+ m_scsihelp->cpu_halt_callback().set_inputline(m_maincpu, INPUT_LINE_HALT);
+ m_scsihelp->timeout_error_callback().set(FUNC(mac_state::scsi_berr_w));
SOFTWARE_LIST(config, "hdd_list").set_original("mac_hdd");
}
diff --git a/src/mame/drivers/mac128.cpp b/src/mame/drivers/mac128.cpp
index 7f88e9a7f95..96705509603 100644
--- a/src/mame/drivers/mac128.cpp
+++ b/src/mame/drivers/mac128.cpp
@@ -88,9 +88,6 @@ Scanline 0 is the start of vblank.
#include "bus/mackbd/mackbd.h"
#include "bus/macpds/hyperdrive.h"
-#include "bus/scsi/scsicd.h"
-#include "bus/scsi/scsi.h"
-#include "bus/scsi/scsihd.h"
#include "cpu/m68000/m68000.h"
#include "machine/6522via.h"
#include "machine/iwm.h"
@@ -98,14 +95,13 @@ Scanline 0 is the start of vblank.
#include "machine/ncr5380n.h"
#include "machine/nscsi_bus.h"
#include "machine/rescap.h"
-#include "bus/nscsi/hd.h"
-#include "bus/nscsi/cd.h"
-#include "machine/ncr5380.h"
+#include "bus/nscsi/devices.h"
#include "machine/ram.h"
#include "machine/applefdintf.h"
#include "machine/timer.h"
#include "machine/z80scc.h"
#include "machine/macadb.h"
+#include "machine/macscsi.h"
#include "sound/dac.h"
#include "sound/flt_biquad.h"
#include "bus/macpds/pds_tpdfpd.h"
@@ -139,8 +135,8 @@ public:
m_via(*this, "via6522_0"),
m_macadb(*this, "macadb"),
m_ram(*this, RAM_TAG),
- m_ncr5380(*this, "ncr5380"),
m_scsibus(*this, "scsibus"),
+ m_scsihelp(*this, "scsihelp"),
m_ncr5380n(*this, "scsibus:7:ncr5380n"),
m_iwm(*this, "fdc"),
m_floppy(*this, "fdc:%d", 0U),
@@ -175,8 +171,8 @@ private:
required_device<via6522_device> m_via;
optional_device<macadb_device> m_macadb;
required_device<ram_device> m_ram;
- optional_device<ncr5380_device> m_ncr5380;
optional_device<nscsi_bus_device> m_scsibus;
+ optional_device<mac_scsi_helper_device> m_scsihelp;
optional_device<ncr5380n_device> m_ncr5380n;
required_device<applefdintf_device> m_iwm;
required_device_array<floppy_connector, 2> m_floppy;
@@ -218,6 +214,7 @@ private:
void macse_scsi_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
DECLARE_WRITE_LINE_MEMBER(scsi_irq_w);
DECLARE_WRITE_LINE_MEMBER(scsi_drq_w);
+ void scsi_berr_w(uint8_t data);
DECLARE_WRITE_LINE_MEMBER(set_scc_interrupt);
DECLARE_WRITE_LINE_MEMBER(vblank_w);
@@ -619,6 +616,11 @@ WRITE_LINE_MEMBER(mac128_state::scsi_drq_w)
m_scsi_drq = state;
}
+void mac128_state::scsi_berr_w(uint8_t data)
+{
+ m_maincpu->pulse_input_line(M68K_LINE_BUSERROR, attotime::zero);
+}
+
uint16_t mac128_state::macplus_scsi_r(offs_t offset, uint16_t mem_mask)
{
int reg = (offset >> 3) & 0xf;
@@ -664,12 +666,7 @@ uint16_t mac128_state::macse_scsi_r(offs_t offset, uint16_t mem_mask)
// logerror("macplus_scsi_r: offset %x mask %x\n", offset, mem_mask);
- if ((reg == 6) && (offset == 0x130))
- {
- reg = R5380_CURDATA_DTACK;
- }
-
- return m_ncr5380->ncr5380_read_reg(reg)<<8;
+ return m_scsihelp->read_wrapper(BIT(offset, 8), reg)<<8;
}
void mac128_state::macse_scsi_w(offs_t offset, uint16_t data, uint16_t mem_mask)
@@ -678,12 +675,7 @@ void mac128_state::macse_scsi_w(offs_t offset, uint16_t data, uint16_t mem_mask)
// logerror("macplus_scsi_w: data %x offset %x mask %x\n", data, offset, mem_mask);
- if ((reg == 0) && (offset == 0x100))
- {
- reg = R5380_OUTDATA_DTACK;
- }
-
- m_ncr5380->ncr5380_write_reg(reg, data);
+ m_scsihelp->write_wrapper(BIT(offset, 8), reg, data>>8);
}
void mac128_state::scc_mouse_irq(int x, int y)
@@ -1125,12 +1117,6 @@ void mac128_state::macse_map(address_map &map)
MACHINE DRIVERS
***************************************************************************/
-static void mac_scsi_devices(device_slot_interface &device)
-{
- device.option_add("harddisk", NSCSI_HARDDISK);
- device.option_add("cdrom", NSCSI_CDROM);
-}
-
static void mac_pds_cards(device_slot_interface &device)
{
device.option_add("hyperdrive", PDS_HYPERDRIVE); // GCC HyperDrive ST-506 interface
@@ -1256,7 +1242,6 @@ void mac128_state::macse(machine_config &config)
config.device_remove("kbd");
config.device_remove("pds");
- config.device_remove("scsibus");
IWM(config.replace(), m_iwm, C7M*2);
m_iwm->phases_cb().set(FUNC(mac128_state::phases_w));
@@ -1265,13 +1250,19 @@ void mac128_state::macse(machine_config &config)
applefdintf_device::add_35(config, m_floppy[0]);
applefdintf_device::add_35(config, m_floppy[1]);
- scsi_port_device &scsibus(SCSI_PORT(config, "scsi"));
- scsibus.set_slot_device(1, "harddisk", SCSIHD, DEVICE_INPUT_DEFAULTS_NAME(SCSI_ID_6));
- scsibus.set_slot_device(2, "harddisk", SCSIHD, DEVICE_INPUT_DEFAULTS_NAME(SCSI_ID_5));
+ MAC_SCSI_HELPER(config, m_scsihelp);
+ m_scsihelp->scsi_read_callback().set(m_ncr5380n, FUNC(ncr5380n_device::read));
+ m_scsihelp->scsi_write_callback().set(m_ncr5380n, FUNC(ncr5380n_device::write));
+ m_scsihelp->scsi_dma_read_callback().set(m_ncr5380n, FUNC(ncr5380n_device::dma_r));
+ m_scsihelp->scsi_dma_write_callback().set(m_ncr5380n, FUNC(ncr5380n_device::dma_w));
+ m_scsihelp->cpu_halt_callback().set_inputline(m_maincpu, INPUT_LINE_HALT);
+ m_scsihelp->timeout_error_callback().set(FUNC(mac128_state::scsi_berr_w));
- NCR5380(config, m_ncr5380, C7M);
- m_ncr5380->set_scsi_port("scsi");
- m_ncr5380->irq_callback().set(FUNC(mac128_state::scsi_irq_w));
+ subdevice<nscsi_connector>("scsibus:7")->set_option_machine_config("ncr5380n", [this](device_t *device) {
+ ncr5380n_device &adapter = downcast<ncr5380n_device &>(*device);
+ adapter.irq_handler().set(*this, FUNC(mac128_state::scsi_irq_w));
+ adapter.drq_handler().set(m_scsihelp, FUNC(mac_scsi_helper_device::drq_w));
+ });
MACADB(config, m_macadb, C7M);
m_macadb->via_clock_callback().set(m_via, FUNC(via6522_device::write_cb1));
@@ -1312,6 +1303,12 @@ void mac128_state::macclasc(machine_config &config)
config.device_remove("pds");
config.device_remove("sepds");
+
+ NSCSI_CONNECTOR(config.replace(), "scsibus:7").option_set("ncr5380n", NCR53C80).machine_config([this](device_t *device) {
+ ncr5380n_device &adapter = downcast<ncr5380n_device &>(*device);
+ adapter.irq_handler().set(*this, FUNC(mac128_state::scsi_irq_w));
+ adapter.drq_handler().set(m_scsihelp, FUNC(mac_scsi_helper_device::drq_w));
+ });
}
static INPUT_PORTS_START( macplus )
diff --git a/src/mame/drivers/macprtb.cpp b/src/mame/drivers/macprtb.cpp
index ed539694429..7736cb0f334 100644
--- a/src/mame/drivers/macprtb.cpp
+++ b/src/mame/drivers/macprtb.cpp
@@ -98,9 +98,10 @@
#include "machine/timer.h"
#include "machine/z80scc.h"
#include "machine/macadb.h"
-#include "machine/ncr5380.h"
-#include "bus/scsi/scsi.h"
-#include "bus/scsi/scsihd.h"
+#include "machine/macscsi.h"
+#include "machine/ncr5380n.h"
+#include "machine/nscsi_bus.h"
+#include "bus/nscsi/devices.h"
#include "sound/asc.h"
#include "formats/ap_dsk35.h"
@@ -109,9 +110,9 @@
#include "softlist.h"
#include "speaker.h"
-#define C7M (7833600)
-#define C15M (C7M*2)
-#define C32M (C15M*2)
+#define C32M (31.3344_MHz_XTAL)
+#define C15M (C32M/2)
+#define C7M (C32M/4)
class macportable_state : public driver_device
{
@@ -122,7 +123,8 @@ public:
m_pmu(*this, "pmu"),
m_via1(*this, "via1"),
m_macadb(*this, "macadb"),
- m_ncr5380(*this, "ncr5380"),
+ m_ncr5380(*this, "scsi:7:ncr5380"),
+ m_scsihelp(*this, "scsihelp"),
m_ram(*this, RAM_TAG),
m_swim(*this, "fdc"),
m_floppy(*this, "fdc:%d", 0U),
@@ -145,7 +147,8 @@ private:
required_device<m50753_device> m_pmu;
required_device<via6522_device> m_via1;
required_device<macadb_device> m_macadb;
- required_device<ncr5380_device> m_ncr5380;
+ required_device<ncr53c80_device> m_ncr5380;
+ required_device<mac_scsi_helper_device> m_scsihelp;
required_device<ram_device> m_ram;
required_device<applefdintf_device> m_swim;
required_device_array<floppy_connector, 2> m_floppy;
@@ -177,7 +180,7 @@ private:
DECLARE_WRITE_LINE_MEMBER(via_irq_w);
TIMER_CALLBACK_MEMBER(mac_6015_tick);
int m_via_cycles, m_via_interrupt, m_scc_interrupt, m_asc_interrupt, m_last_taken_interrupt;
- int m_irq_count, m_ca1_data, m_ca2_data;
+ int m_ca1_data;
void phases_w(uint8_t phases);
void devsel_w(uint8_t devsel);
@@ -187,6 +190,7 @@ private:
uint16_t scsi_r(offs_t offset, uint16_t mem_mask);
void scsi_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ void scsi_berr_w(uint8_t data);
uint16_t mac_scc_r(offs_t offset)
{
@@ -220,9 +224,9 @@ private:
field_interrupts();
}
- u8 m_pmu_via_bus, m_pmu_ack, m_pmu_req;
- u8 pmu_data_r() { return m_pmu_via_bus; }
- void pmu_data_w(u8 data) { m_pmu_via_bus = data; }
+ u8 m_pmu_to_via, m_pmu_from_via, m_pmu_ack, m_pmu_req;
+ u8 pmu_data_r() { return m_pmu_from_via; }
+ void pmu_data_w(u8 data) { m_pmu_to_via = data; }
u8 pmu_comms_r() { return (m_pmu_req<<7); }
void pmu_comms_w(u8 data)
{
@@ -231,6 +235,7 @@ private:
m_maincpu->set_input_line(INPUT_LINE_HALT, CLEAR_LINE);
}
+ m_via1->write_ca2(BIT(data, 4));
m_via1->write_cb1(BIT(data, 5));
m_pmu_ack = BIT(data, 6);
@@ -280,8 +285,9 @@ void macportable_state::machine_start()
m_via_cycles = -50;
m_via_interrupt = m_scc_interrupt = m_asc_interrupt = 0;
m_last_taken_interrupt = -1;
- m_irq_count = m_ca1_data = m_ca2_data = 0;
- m_pmu_via_bus = 0;
+ m_ca1_data = 0;
+ m_pmu_to_via = 0;
+ m_pmu_from_via = 0;
m_pmu_ack = m_pmu_req = 0;
m_adb_line = 1;
@@ -294,9 +300,8 @@ void macportable_state::machine_reset()
m_overlay = true;
m_via_interrupt = m_scc_interrupt = 0;
m_last_taken_interrupt = -1;
- m_irq_count = m_ca1_data = m_ca2_data = 0;
+ m_ca1_data = 0;
- m_pmu_via_bus = 0;
m_pmu_ack = 1;
// start 60.15 Hz timer
@@ -391,15 +396,6 @@ TIMER_CALLBACK_MEMBER(macportable_state::mac_6015_tick)
m_pmu->set_input_line(m50753_device::M50753_INT1_LINE, ASSERT_LINE);
m_macadb->adb_vblank();
-
- if (++m_irq_count == 60)
- {
- m_irq_count = 0;
-
- m_ca2_data ^= 1;
- /* signal 1 Hz irq on CA2 input on the VIA */
- m_via1->write_ca2(m_ca2_data);
- }
}
uint16_t macportable_state::scsi_r(offs_t offset, uint16_t mem_mask)
@@ -408,12 +404,9 @@ uint16_t macportable_state::scsi_r(offs_t offset, uint16_t mem_mask)
// logerror("macplus_scsi_r: offset %x mask %x\n", offset, mem_mask);
- if ((reg == 6) && (offset == 0x130))
- {
- reg = R5380_CURDATA_DTACK;
- }
+ bool pseudo_dma = (reg == 6) && (offset == 0x130);
- return m_ncr5380->ncr5380_read_reg(reg) << 8;
+ return m_scsihelp->read_wrapper(pseudo_dma, reg) << 8;
}
void macportable_state::scsi_w(offs_t offset, uint16_t data, uint16_t mem_mask)
@@ -422,13 +415,16 @@ void macportable_state::scsi_w(offs_t offset, uint16_t data, uint16_t mem_mask)
// logerror("macplus_scsi_w: data %x offset %x mask %x\n", data, offset, mem_mask);
- if ((reg == 0) && (offset == 0x100))
- {
- reg = R5380_OUTDATA_DTACK;
- }
+ bool pseudo_dma = (reg == 0) && (offset == 0x100);
+
+ m_scsihelp->write_wrapper(pseudo_dma, reg, data);
+}
- m_ncr5380->ncr5380_write_reg(reg, data);
+void macportable_state::scsi_berr_w(uint8_t data)
+{
+ m_maincpu->pulse_input_line(M68K_LINE_BUSERROR, attotime::zero);
}
+
/***************************************************************************
ADDRESS MAPS
***************************************************************************/
@@ -449,7 +445,7 @@ void macportable_state::macprtb_map(address_map &map)
uint8_t macportable_state::mac_via_in_a()
{
- return m_pmu_via_bus;
+ return m_pmu_to_via;
}
uint8_t macportable_state::mac_via_in_b()
@@ -459,7 +455,7 @@ uint8_t macportable_state::mac_via_in_b()
void macportable_state::mac_via_out_a(uint8_t data)
{
- m_pmu_via_bus = data;
+ m_pmu_from_via = data;
}
void macportable_state::mac_via_out_b(uint8_t data)
@@ -515,10 +511,12 @@ void macportable_state::macprtb(machine_config &config)
M50753(config, m_pmu, 3.93216_MHz_XTAL);
m_pmu->read_p<2>().set(FUNC(macportable_state::pmu_data_r));
m_pmu->write_p<2>().set(FUNC(macportable_state::pmu_data_w));
+ m_pmu->set_pullups<2>(0xff); // internal pullup option?
m_pmu->read_p<3>().set(FUNC(macportable_state::pmu_comms_r));
m_pmu->write_p<3>().set(FUNC(macportable_state::pmu_comms_w));
m_pmu->read_p<4>().set(FUNC(macportable_state::pmu_adb_r));
m_pmu->write_p<4>().set(FUNC(macportable_state::pmu_adb_w));
+ m_pmu->set_pullups<4>(0x0f); // external pullups
m_pmu->read_in_p().set(FUNC(macportable_state::pmu_in_r));
m_pmu->ad_in<0>().set(FUNC(macportable_state::ad_in_r));
m_pmu->ad_in<1>().set(FUNC(macportable_state::ad_in_r));
@@ -546,12 +544,27 @@ void macportable_state::macprtb(machine_config &config)
applefdintf_device::add_35_hd(config, m_floppy[0]);
applefdintf_device::add_35_nc(config, m_floppy[1]);
- scsi_port_device &scsibus(SCSI_PORT(config, "scsi"));
- scsibus.set_slot_device(1, "harddisk", SCSIHD, DEVICE_INPUT_DEFAULTS_NAME(SCSI_ID_6));
- scsibus.set_slot_device(2, "harddisk", SCSIHD, DEVICE_INPUT_DEFAULTS_NAME(SCSI_ID_5));
-
- NCR5380(config, m_ncr5380, C7M);
- m_ncr5380->set_scsi_port("scsi");
+ NSCSI_BUS(config, "scsi");
+ NSCSI_CONNECTOR(config, "scsi:0", mac_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:1", mac_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:2", mac_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:3", mac_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:4", mac_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:5", mac_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:6", mac_scsi_devices, "harddisk");
+ NSCSI_CONNECTOR(config, "scsi:7").option_set("ncr5380", NCR53C80).machine_config([this](device_t *device) {
+ ncr53c80_device &adapter = downcast<ncr53c80_device &>(*device);
+ adapter.irq_handler().set(m_via1, FUNC(r65c22_device::write_cb2));
+ adapter.drq_handler().set(m_scsihelp, FUNC(mac_scsi_helper_device::drq_w));
+ });
+
+ MAC_SCSI_HELPER(config, m_scsihelp);
+ m_scsihelp->scsi_read_callback().set(m_ncr5380, FUNC(ncr53c80_device::read));
+ m_scsihelp->scsi_write_callback().set(m_ncr5380, FUNC(ncr53c80_device::write));
+ m_scsihelp->scsi_dma_read_callback().set(m_ncr5380, FUNC(ncr53c80_device::dma_r));
+ m_scsihelp->scsi_dma_write_callback().set(m_ncr5380, FUNC(ncr53c80_device::dma_w));
+ m_scsihelp->cpu_halt_callback().set_inputline(m_maincpu, INPUT_LINE_HALT);
+ m_scsihelp->timeout_error_callback().set(FUNC(macportable_state::scsi_berr_w));
SCC85C30(config, m_scc, C7M);
// m_scc->intrq_callback().set(FUNC(macportable_state::set_scc_interrupt));
@@ -576,6 +589,7 @@ void macportable_state::macprtb(machine_config &config)
m_ram->set_extra_options("1M,3M,5M,7M,9M");
SOFTWARE_LIST(config, "flop35_list").set_original("mac_flop");
+ SOFTWARE_LIST(config, "hdd_list").set_original("mac_hdd");
}
ROM_START(macprtb)
diff --git a/src/mame/drivers/macpwrbk030.cpp b/src/mame/drivers/macpwrbk030.cpp
index 4c5a5110b30..65aba47ed8c 100644
--- a/src/mame/drivers/macpwrbk030.cpp
+++ b/src/mame/drivers/macpwrbk030.cpp
@@ -106,9 +106,10 @@
#include "machine/timer.h"
#include "machine/z80scc.h"
#include "machine/macadb.h"
-#include "machine/ncr5380.h"
-#include "bus/scsi/scsi.h"
-#include "bus/scsi/scsihd.h"
+#include "machine/macscsi.h"
+#include "machine/ncr5380n.h"
+#include "machine/nscsi_bus.h"
+#include "bus/nscsi/devices.h"
#include "sound/asc.h"
#include "formats/ap_dsk35.h"
@@ -117,9 +118,9 @@
#include "softlist.h"
#include "speaker.h"
-#define C7M (7833600)
-#define C15M (C7M*2)
-#define C32M (C15M*2)
+#define C32M (31.3344_MHz_XTAL)
+#define C15M (C32M/2)
+#define C7M (C32M/4)
class macpb030_state : public driver_device
{
@@ -131,7 +132,8 @@ public:
m_via1(*this, "via1"),
m_via2(*this, "via2"),
m_macadb(*this, "macadb"),
- m_ncr5380(*this, "ncr5380"),
+ m_ncr5380(*this, "scsi:7:ncr5380"),
+ m_scsihelp(*this, "scsihelp"),
m_ram(*this, RAM_TAG),
m_swim(*this, "fdc"),
m_floppy(*this, "fdc:%d", 0U),
@@ -164,7 +166,8 @@ private:
required_device<via6522_device> m_via1;
required_device<via6522_device> m_via2;
required_device<macadb_device> m_macadb;
- required_device<ncr5380_device> m_ncr5380;
+ required_device<ncr53c80_device> m_ncr5380;
+ required_device<mac_scsi_helper_device> m_scsihelp;
required_device<ram_device> m_ram;
required_device<applefdintf_device> m_swim;
required_device_array<floppy_connector, 2> m_floppy;
@@ -217,6 +220,7 @@ private:
void scsi_w(offs_t offset, u16 data, u16 mem_mask);
uint32_t scsi_drq_r(offs_t offset, uint32_t mem_mask = ~0);
void scsi_drq_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+ void scsi_berr_w(uint8_t data);
u16 mac_scc_r(offs_t offset)
{
mac_via_sync();
@@ -607,12 +611,9 @@ u16 macpb030_state::scsi_r(offs_t offset, u16 mem_mask)
//printf("scsi_r: offset %x mask %x\n", offset, mem_mask);
- if ((reg == 6) && (offset == 0x130))
- {
- reg = R5380_CURDATA_DTACK;
- }
+ bool pseudo_dma = (reg == 6) && (offset == 0x130);
- return m_ncr5380->ncr5380_read_reg(reg) << 8;
+ return m_scsihelp->read_wrapper(pseudo_dma, reg) << 8;
}
void macpb030_state::scsi_w(offs_t offset, u16 data, u16 mem_mask)
@@ -621,12 +622,9 @@ void macpb030_state::scsi_w(offs_t offset, u16 data, u16 mem_mask)
//printf("scsi_w: data %x offset %x mask %x\n", data, offset, mem_mask);
- if ((reg == 0) && (offset == 0x100))
- {
- reg = R5380_OUTDATA_DTACK;
- }
+ bool pseudo_dma = (reg == 0) && (offset == 0x100);
- m_ncr5380->ncr5380_write_reg(reg, data>>8);
+ m_scsihelp->write_wrapper(pseudo_dma, reg, data>>8);
}
uint32_t macpb030_state::scsi_drq_r(offs_t offset, uint32_t mem_mask)
@@ -634,13 +632,13 @@ uint32_t macpb030_state::scsi_drq_r(offs_t offset, uint32_t mem_mask)
switch (mem_mask)
{
case 0xff000000:
- return m_ncr5380->ncr5380_read_reg(R5380_CURDATA_DTACK)<<24;
+ return m_scsihelp->read_wrapper(true, 6)<<24;
case 0xffff0000:
- return (m_ncr5380->ncr5380_read_reg(R5380_CURDATA_DTACK)<<24) | (m_ncr5380->ncr5380_read_reg(R5380_CURDATA_DTACK)<<16);
+ return (m_scsihelp->read_wrapper(true, 6)<<24) | (m_scsihelp->read_wrapper(true, 6)<<16);
case 0xffffffff:
- return (m_ncr5380->ncr5380_read_reg(R5380_CURDATA_DTACK)<<24) | (m_ncr5380->ncr5380_read_reg(R5380_CURDATA_DTACK)<<16) | (m_ncr5380->ncr5380_read_reg(R5380_CURDATA_DTACK)<<8) | m_ncr5380->ncr5380_read_reg(R5380_CURDATA_DTACK);
+ return (m_scsihelp->read_wrapper(true, 6)<<24) | (m_scsihelp->read_wrapper(true, 6)<<16) | (m_scsihelp->read_wrapper(true, 6)<<8) | m_scsihelp->read_wrapper(true, 6);
default:
logerror("scsi_drq_r: unknown mem_mask %08x\n", mem_mask);
@@ -654,19 +652,19 @@ void macpb030_state::scsi_drq_w(offs_t offset, uint32_t data, uint32_t mem_mask)
switch (mem_mask)
{
case 0xff000000:
- m_ncr5380->ncr5380_write_reg(R5380_OUTDATA_DTACK, data>>24);
+ m_scsihelp->write_wrapper(true, 0, data>>24);
break;
case 0xffff0000:
- m_ncr5380->ncr5380_write_reg(R5380_OUTDATA_DTACK, data>>24);
- m_ncr5380->ncr5380_write_reg(R5380_OUTDATA_DTACK, data>>16);
+ m_scsihelp->write_wrapper(true, 0, data>>24);
+ m_scsihelp->write_wrapper(true, 0, data>>16);
break;
case 0xffffffff:
- m_ncr5380->ncr5380_write_reg(R5380_OUTDATA_DTACK, data>>24);
- m_ncr5380->ncr5380_write_reg(R5380_OUTDATA_DTACK, data>>16);
- m_ncr5380->ncr5380_write_reg(R5380_OUTDATA_DTACK, data>>8);
- m_ncr5380->ncr5380_write_reg(R5380_OUTDATA_DTACK, data&0xff);
+ m_scsihelp->write_wrapper(true, 0, data>>24);
+ m_scsihelp->write_wrapper(true, 0, data>>16);
+ m_scsihelp->write_wrapper(true, 0, data>>8);
+ m_scsihelp->write_wrapper(true, 0, data&0xff);
break;
default:
@@ -675,6 +673,11 @@ void macpb030_state::scsi_drq_w(offs_t offset, uint32_t data, uint32_t mem_mask)
}
}
+void macpb030_state::scsi_berr_w(uint8_t data)
+{
+ m_maincpu->pulse_input_line(M68K_LINE_BUSERROR, attotime::zero);
+}
+
uint8_t macpb030_state::mac_gsc_r(offs_t offset)
{
if (offset == 1)
@@ -919,12 +922,26 @@ void macpb030_state::macpb140(machine_config &config)
applefdintf_device::add_35_hd(config, m_floppy[0]);
applefdintf_device::add_35_nc(config, m_floppy[1]);
- scsi_port_device &scsibus(SCSI_PORT(config, "scsi"));
- scsibus.set_slot_device(1, "harddisk", SCSIHD, DEVICE_INPUT_DEFAULTS_NAME(SCSI_ID_6));
- scsibus.set_slot_device(2, "harddisk", SCSIHD, DEVICE_INPUT_DEFAULTS_NAME(SCSI_ID_5));
-
- NCR5380(config, m_ncr5380, C7M);
- m_ncr5380->set_scsi_port("scsi");
+ NSCSI_BUS(config, "scsi");
+ NSCSI_CONNECTOR(config, "scsi:0", mac_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:1", mac_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:2", mac_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:3", mac_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:4", mac_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:5", mac_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:6", mac_scsi_devices, "harddisk");
+ NSCSI_CONNECTOR(config, "scsi:7").option_set("ncr5380", NCR53C80).machine_config([this](device_t *device) {
+ ncr53c80_device &adapter = downcast<ncr53c80_device &>(*device);
+ adapter.drq_handler().set(m_scsihelp, FUNC(mac_scsi_helper_device::drq_w));
+ });
+
+ MAC_SCSI_HELPER(config, m_scsihelp);
+ m_scsihelp->scsi_read_callback().set(m_ncr5380, FUNC(ncr53c80_device::read));
+ m_scsihelp->scsi_write_callback().set(m_ncr5380, FUNC(ncr53c80_device::write));
+ m_scsihelp->scsi_dma_read_callback().set(m_ncr5380, FUNC(ncr53c80_device::dma_r));
+ m_scsihelp->scsi_dma_write_callback().set(m_ncr5380, FUNC(ncr53c80_device::dma_w));
+ m_scsihelp->cpu_halt_callback().set_inputline(m_maincpu, INPUT_LINE_HALT);
+ m_scsihelp->timeout_error_callback().set(FUNC(macpb030_state::scsi_berr_w));
SCC85C30(config, m_scc, C7M);
// m_scc->intrq_callback().set(FUNC(macpb030_state::set_scc_interrupt));
@@ -957,6 +974,7 @@ void macpb030_state::macpb140(machine_config &config)
m_ram->set_extra_options("4M,6M,8M");
SOFTWARE_LIST(config, "flop35_list").set_original("mac_flop");
+ SOFTWARE_LIST(config, "hdd_list").set_original("mac_hdd");
}
// PowerBook 145 = 140 @ 25 MHz (still 2MB RAM - the 145B upped that to 4MB)
@@ -1015,12 +1033,26 @@ void macpb030_state::macpb160(machine_config &config)
applefdintf_device::add_35_hd(config, m_floppy[0]);
applefdintf_device::add_35_nc(config, m_floppy[1]);
- scsi_port_device &scsibus(SCSI_PORT(config, "scsi"));
- scsibus.set_slot_device(1, "harddisk", SCSIHD, DEVICE_INPUT_DEFAULTS_NAME(SCSI_ID_6));
- scsibus.set_slot_device(2, "harddisk", SCSIHD, DEVICE_INPUT_DEFAULTS_NAME(SCSI_ID_5));
-
- NCR5380(config, m_ncr5380, C7M);
- m_ncr5380->set_scsi_port("scsi");
+ NSCSI_BUS(config, "scsi");
+ NSCSI_CONNECTOR(config, "scsi:0", mac_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:1", mac_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:2", mac_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:3", mac_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:4", mac_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:5", mac_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:6", mac_scsi_devices, "harddisk");
+ NSCSI_CONNECTOR(config, "scsi:7").option_set("ncr5380", NCR53C80).machine_config([this](device_t *device) {
+ ncr53c80_device &adapter = downcast<ncr53c80_device &>(*device);
+ adapter.drq_handler().set(m_scsihelp, FUNC(mac_scsi_helper_device::drq_w));
+ });
+
+ MAC_SCSI_HELPER(config, m_scsihelp);
+ m_scsihelp->scsi_read_callback().set(m_ncr5380, FUNC(ncr53c80_device::read));
+ m_scsihelp->scsi_write_callback().set(m_ncr5380, FUNC(ncr53c80_device::write));
+ m_scsihelp->scsi_dma_read_callback().set(m_ncr5380, FUNC(ncr53c80_device::dma_r));
+ m_scsihelp->scsi_dma_write_callback().set(m_ncr5380, FUNC(ncr53c80_device::dma_w));
+ m_scsihelp->cpu_halt_callback().set_inputline(m_maincpu, INPUT_LINE_HALT);
+ m_scsihelp->timeout_error_callback().set(FUNC(macpb030_state::scsi_berr_w));
SCC85C30(config, m_scc, C7M);
// m_scc->intrq_callback().set(FUNC(macpb030_state::set_scc_interrupt));
@@ -1053,6 +1085,7 @@ void macpb030_state::macpb160(machine_config &config)
m_ram->set_extra_options("4M,6M,8M");
SOFTWARE_LIST(config, "flop35_list").set_original("mac_flop");
+ SOFTWARE_LIST(config, "hdd_list").set_original("mac_hdd");
}
void macpb030_state::macpb180(machine_config &config)
diff --git a/src/mame/drivers/macquadra700.cpp b/src/mame/drivers/macquadra700.cpp
index 2c373fbbaf6..4446f441b87 100644
--- a/src/mame/drivers/macquadra700.cpp
+++ b/src/mame/drivers/macquadra700.cpp
@@ -26,8 +26,7 @@
#include "sound/asc.h"
#include "formats/ap_dsk35.h"
-#include "bus/nscsi/cd.h"
-#include "bus/nscsi/hd.h"
+#include "bus/nscsi/devices.h"
#include "bus/nubus/nubus.h"
#include "bus/nubus/nubus_48gc.h"
@@ -936,12 +935,6 @@ static void mac_nubus_cards(device_slot_interface &device)
device.option_add("laserview", NUBUS_LASERVIEW); /* Sigma Designs LaserView monochrome video card */
}
-static void mac_scsi_devices(device_slot_interface &device)
-{
- device.option_add("harddisk", NSCSI_HARDDISK);
- device.option_add("cdrom", NSCSI_CDROM);
-}
-
void macquadra_state::macqd700(machine_config &config)
{
/* basic machine hardware */
diff --git a/src/mame/includes/mac.h b/src/mame/includes/mac.h
index 05dd48a6f5f..4ab3bddd2ec 100644
--- a/src/mame/includes/mac.h
+++ b/src/mame/includes/mac.h
@@ -14,6 +14,8 @@
#include "machine/8530scc.h"
#include "machine/6522via.h"
+#include "machine/ncr5380n.h"
+#include "machine/nscsi_bus.h"
#include "machine/ram.h"
#include "machine/timer.h"
#include "machine/egret.h"
@@ -22,8 +24,8 @@
#include "bus/nubus/nubus.h"
#include "bus/macpds/macpds.h"
#include "machine/applefdintf.h"
-#include "machine/ncr5380.h"
#include "machine/macrtc.h"
+#include "machine/macscsi.h"
#include "sound/asc.h"
#include "sound/dac.h"
#include "cpu/m68000/m68000.h"
@@ -59,7 +61,8 @@ public:
m_macadb(*this, "macadb"),
m_ram(*this, RAM_TAG),
m_scc(*this, "scc"),
- m_ncr5380(*this, "ncr5380"),
+ m_ncr5380(*this, "scsi:7:ncr5380"),
+ m_scsihelp(*this, "scsihelp"),
m_fdc(*this, "fdc"),
m_floppy(*this, "fdc:%d", 0U),
m_rtc(*this, "rtc"),
@@ -196,7 +199,8 @@ private:
optional_device<macadb_device> m_macadb;
required_device<ram_device> m_ram;
required_device<scc8530_legacy_device> m_scc;
- optional_device<ncr5380_device> m_ncr5380;
+ required_device<ncr53c80_device> m_ncr5380;
+ required_device<mac_scsi_helper_device> m_scsihelp;
required_device<applefdintf_device> m_fdc;
required_device_array<floppy_connector, 2> m_floppy;
optional_device<rtc3430042_device> m_rtc;
@@ -286,6 +290,7 @@ private:
void macii_scsi_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
uint32_t macii_scsi_drq_r(offs_t offset, uint32_t mem_mask = ~0);
void macii_scsi_drq_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+ void scsi_berr_w(uint8_t data);
uint32_t rbv_ramdac_r();
void rbv_ramdac_w(offs_t offset, uint32_t data);
diff --git a/src/mame/machine/mac.cpp b/src/mame/machine/mac.cpp
index f324b5a582d..1070ecaaa5d 100644
--- a/src/mame/machine/mac.cpp
+++ b/src/mame/machine/mac.cpp
@@ -468,12 +468,9 @@ uint16_t mac_state::macplus_scsi_r(offs_t offset, uint16_t mem_mask)
// logerror("macplus_scsi_r: offset %x mask %x\n", offset, mem_mask);
- if ((reg == 6) && (offset == 0x130))
- {
- reg = R5380_CURDATA_DTACK;
- }
+ bool pseudo_dma = (reg == 6) && (offset == 0x130);
- return m_ncr5380->ncr5380_read_reg(reg)<<8;
+ return m_scsihelp->read_wrapper(pseudo_dma, reg)<<8;
}
uint32_t mac_state::macii_scsi_drq_r(offs_t offset, uint32_t mem_mask)
@@ -481,13 +478,13 @@ uint32_t mac_state::macii_scsi_drq_r(offs_t offset, uint32_t mem_mask)
switch (mem_mask)
{
case 0xff000000:
- return m_ncr5380->ncr5380_read_reg(R5380_CURDATA_DTACK)<<24;
+ return m_scsihelp->read_wrapper(true, 6)<<24;
case 0xffff0000:
- return (m_ncr5380->ncr5380_read_reg(R5380_CURDATA_DTACK)<<24) | (m_ncr5380->ncr5380_read_reg(R5380_CURDATA_DTACK)<<16);
+ return (m_scsihelp->read_wrapper(true, 6)<<24) | (m_scsihelp->read_wrapper(true, 6)<<16);
case 0xffffffff:
- return (m_ncr5380->ncr5380_read_reg(R5380_CURDATA_DTACK)<<24) | (m_ncr5380->ncr5380_read_reg(R5380_CURDATA_DTACK)<<16) | (m_ncr5380->ncr5380_read_reg(R5380_CURDATA_DTACK)<<8) | m_ncr5380->ncr5380_read_reg(R5380_CURDATA_DTACK);
+ return (m_scsihelp->read_wrapper(true, 6)<<24) | (m_scsihelp->read_wrapper(true, 6)<<16) | (m_scsihelp->read_wrapper(true, 6)<<8) | m_scsihelp->read_wrapper(true, 6);
default:
logerror("macii_scsi_drq_r: unknown mem_mask %08x\n", mem_mask);
@@ -501,19 +498,19 @@ void mac_state::macii_scsi_drq_w(offs_t offset, uint32_t data, uint32_t mem_mask
switch (mem_mask)
{
case 0xff000000:
- m_ncr5380->ncr5380_write_reg(R5380_OUTDATA_DTACK, data>>24);
+ m_scsihelp->write_wrapper(true, 0, data>>24);
break;
case 0xffff0000:
- m_ncr5380->ncr5380_write_reg(R5380_OUTDATA_DTACK, data>>24);
- m_ncr5380->ncr5380_write_reg(R5380_OUTDATA_DTACK, data>>16);
+ m_scsihelp->write_wrapper(true, 0, data>>24);
+ m_scsihelp->write_wrapper(true, 0, data>>16);
break;
case 0xffffffff:
- m_ncr5380->ncr5380_write_reg(R5380_OUTDATA_DTACK, data>>24);
- m_ncr5380->ncr5380_write_reg(R5380_OUTDATA_DTACK, data>>16);
- m_ncr5380->ncr5380_write_reg(R5380_OUTDATA_DTACK, data>>8);
- m_ncr5380->ncr5380_write_reg(R5380_OUTDATA_DTACK, data&0xff);
+ m_scsihelp->write_wrapper(true, 0, data>>24);
+ m_scsihelp->write_wrapper(true, 0, data>>16);
+ m_scsihelp->write_wrapper(true, 0, data>>8);
+ m_scsihelp->write_wrapper(true, 0, data&0xff);
break;
default:
@@ -528,12 +525,9 @@ void mac_state::macplus_scsi_w(offs_t offset, uint16_t data, uint16_t mem_mask)
// logerror("macplus_scsi_w: data %x offset %x mask %x\n", data, offset, mem_mask);
- if ((reg == 0) && (offset == 0x100))
- {
- reg = R5380_OUTDATA_DTACK;
- }
+ bool pseudo_dma = (reg == 0) && (offset == 0x100);
- m_ncr5380->ncr5380_write_reg(reg, data);
+ m_scsihelp->write_wrapper(pseudo_dma, reg, data);
}
void mac_state::macii_scsi_w(offs_t offset, uint16_t data, uint16_t mem_mask)
@@ -542,12 +536,9 @@ void mac_state::macii_scsi_w(offs_t offset, uint16_t data, uint16_t mem_mask)
// logerror("macplus_scsi_w: data %x offset %x mask %x (PC=%x)\n", data, offset, mem_mask, m_maincpu->pc());
- if ((reg == 0) && (offset == 0x100))
- {
- reg = R5380_OUTDATA_DTACK;
- }
+ bool pseudo_dma = (reg == 0) && (offset == 0x100);
- m_ncr5380->ncr5380_write_reg(reg, data>>8);
+ m_scsihelp->write_wrapper(pseudo_dma, reg, data>>8);
}
WRITE_LINE_MEMBER(mac_state::mac_scsi_irq)
@@ -561,6 +552,11 @@ WRITE_LINE_MEMBER(mac_state::mac_scsi_irq)
}*/
}
+void mac_state::scsi_berr_w(uint8_t data)
+{
+ m_maincpu->pulse_input_line(M68K_LINE_BUSERROR, attotime::zero);
+}
+
/* *************************************************************************
* SCC
*
diff --git a/src/mame/machine/macscsi.cpp b/src/mame/machine/macscsi.cpp
new file mode 100644
index 00000000000..7a06b246ad2
--- /dev/null
+++ b/src/mame/machine/macscsi.cpp
@@ -0,0 +1,318 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/**********************************************************************
+
+ Apple Macintosh 5380 SCSI helper
+
+ The Macintosh Toolbox's SCSI Manager defines two methods each for
+ reading and writing SCSI data (including data comparisons). All
+ of these methods are implemented using the 5380's pseudo-DMA mode.
+ For SCSIRead and SCSIWrite, the CPU polls DRQ before it reads or
+ writes each byte, but SCSIRBlind and SCSIWBlind, in order to
+ transfer data as quickly as possible, do not perform this check in
+ software except before the very first byte (to give SCSI devices
+ time to react to commands). Rather, the hardware enables DRQ onto
+ DTACK (MC68000) or DSACK0 (MC68020/030) so wait states can be
+ inserted to correspond to SCSI delays. Too long a delay will
+ result in a BERR timeout, and the SCSI Manager anticipates bus
+ errors by inserting its own exception handler in the vector table.
+ The exact timeout is system-dependent. Later Macs will attempt a
+ limited number of recoveries from bus errors during SCSI transfers
+ before exiting with the scBusTOErr code; the MC68000's rudimentary
+ handling of bus errors does not permit this.
+
+ This causes some conflicts between MAME's line-level emulation of
+ the SCSI bus and its current M68000 family core, which has no
+ working concept of wait states and tries to execute each read or
+ write instruction instantaneously. The problems are least
+ pronounced on the Macintosh Plus, which never reads or writes more
+ than one SCSI byte at a time in any case. However, the SE and
+ later models implement the "blind" transfer modes using unrolled
+ loops with MOVEP.L (MC68000) or MOVE.L (MC68020/030) to transfer
+ four bytes at a time (after first transfering a single byte if its
+ buffer pointer is not word-aligned).
+
+ The workaround this device provides is to mediate pseudo-DMA
+ transfers through four-byte FIFOs (implementing these using
+ 32-bit integers is not a coincidence) and halt the CPU to keep
+ the FIFO filled during read operations and emptied during write
+ operations. In the case of read operations, the buffer must of
+ course be filled before CPU attempts its first data read, which
+ could be a MOVEP.L or MOVE.L already. To make read operations a
+ little more realistic, the device waits until the CPU polls DRQ as
+ active before it begins halting the CPU to fill the FIFO. The CPU
+ halt will be released if DRQ is not asserted within a certain
+ time.
+
+ It is possible for the current implementation to lose data if
+ there are still bytes in the FIFO when the pseudo-DMA operation
+ ends. However, this is unlikely to be relevant due to a defect in
+ the SCSI Manager which Apple's documentation warns about.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "macscsi.h"
+
+#define VERBOSE 0
+#include "logmacro.h"
+
+static constexpr u8 BAD_BYTE = 0xbb;
+static constexpr u8 READ_ERROR = 1;
+static constexpr u8 WRITE_ERROR = 0;
+
+// device type definition
+DEFINE_DEVICE_TYPE(MAC_SCSI_HELPER, mac_scsi_helper_device, "scsipdma", "Mac 5380 SCSI helper")
+
+ALLOW_SAVE_TYPE(mac_scsi_helper_device::mode);
+
+mac_scsi_helper_device::mac_scsi_helper_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MAC_SCSI_HELPER, tag, owner, clock)
+ , m_scsi_read_callback(*this)
+ , m_scsi_write_callback(*this)
+ , m_scsi_dma_read_callback(*this)
+ , m_scsi_dma_write_callback(*this)
+ , m_cpu_halt_callback(*this)
+ , m_timeout_error_callback(*this)
+ , m_timeout(attotime::from_usec(16))
+ , m_pseudo_dma_timer(nullptr)
+ , m_mode(mode::NON_DMA)
+ , m_read_fifo_bytes(0)
+ , m_write_fifo_bytes(0)
+ , m_read_fifo_data(0)
+ , m_write_fifo_data(0)
+{
+}
+
+void mac_scsi_helper_device::device_resolve_objects()
+{
+ m_scsi_read_callback.resolve_safe(BAD_BYTE);
+ m_scsi_write_callback.resolve_safe();
+ m_scsi_dma_read_callback.resolve_safe(BAD_BYTE);
+ m_scsi_dma_write_callback.resolve_safe();
+ m_cpu_halt_callback.resolve_safe();
+ m_timeout_error_callback.resolve_safe();
+}
+
+void mac_scsi_helper_device::device_start()
+{
+ m_pseudo_dma_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(mac_scsi_helper_device::timer_callback), this));
+
+ save_item(NAME(m_mode));
+ save_item(NAME(m_read_fifo_bytes));
+ save_item(NAME(m_write_fifo_bytes));
+ save_item(NAME(m_read_fifo_data));
+ save_item(NAME(m_write_fifo_data));
+}
+
+void mac_scsi_helper_device::device_reset()
+{
+ dma_stop();
+
+ m_cpu_halt_callback(CLEAR_LINE);
+ m_pseudo_dma_timer->enable(false);
+}
+
+void mac_scsi_helper_device::read_fifo_process()
+{
+ assert(m_read_fifo_bytes < 4);
+
+ u8 data = m_scsi_dma_read_callback(6);
+ ++m_read_fifo_bytes;
+ LOG("Read byte %02X into FIFO (%d/4 filled)\n", data, m_read_fifo_bytes);
+ m_read_fifo_data |= u32(data) << (32 - m_read_fifo_bytes * 8);
+ if (m_read_fifo_bytes != 4)
+ m_pseudo_dma_timer->adjust(m_timeout);
+ else
+ {
+ m_cpu_halt_callback(CLEAR_LINE);
+ m_pseudo_dma_timer->enable(false);
+ }
+}
+
+void mac_scsi_helper_device::write_fifo_process()
+{
+ assert(m_write_fifo_bytes != 0);
+ --m_write_fifo_bytes;
+ u8 data = BIT(m_write_fifo_data, m_write_fifo_bytes * 8, 8);
+ LOG("Write byte %02X from FIFO (%d left)\n", data, m_write_fifo_bytes);
+ m_scsi_dma_write_callback(0, data);
+
+ if (m_write_fifo_bytes != 0)
+ m_pseudo_dma_timer->adjust(m_timeout);
+ else
+ {
+ m_cpu_halt_callback(CLEAR_LINE);
+ m_pseudo_dma_timer->enable(false);
+ }
+}
+
+WRITE_LINE_MEMBER(mac_scsi_helper_device::drq_w)
+{
+ if (state)
+ {
+ if (m_mode == mode::READ_DMA && m_read_fifo_bytes < 4)
+ read_fifo_process();
+ else if ((m_mode == mode::WRITE_DMA || m_mode == mode::BAD_DMA) && m_write_fifo_bytes != 0)
+ write_fifo_process();
+ }
+}
+
+TIMER_CALLBACK_MEMBER(mac_scsi_helper_device::timer_callback)
+{
+ if (m_mode == mode::WRITE_DMA && m_write_fifo_bytes != 0 && BIT(m_scsi_read_callback(5), 6))
+ write_fifo_process();
+ else if (m_mode == mode::READ_DMA || m_mode == mode::WRITE_DMA)
+ {
+ LOG("DMA timed out\n");
+ m_cpu_halt_callback(CLEAR_LINE);
+ }
+ else
+ dma_stop();
+}
+
+void mac_scsi_helper_device::dma_stop()
+{
+ if (m_read_fifo_bytes != 0)
+ logerror("%s: %d unread byte(s) lost (%08X)\n", machine().describe_context(), m_read_fifo_bytes, m_read_fifo_data);
+ if (m_write_fifo_bytes != 0)
+ logerror("%s: %d unwritten byte(s) lost (%08X)\n", machine().describe_context(), m_write_fifo_bytes, m_write_fifo_data);
+
+ m_mode = mode::NON_DMA;
+ m_read_fifo_bytes = 0;
+ m_write_fifo_bytes = 0;
+ m_read_fifo_data = 0;
+ m_write_fifo_data = 0;
+}
+
+u8 mac_scsi_helper_device::read_wrapper(bool pseudo_dma, offs_t offset)
+{
+ u8 data = BAD_BYTE;
+ switch (offset & 7)
+ {
+ case 2:
+ data = m_scsi_read_callback(2);
+ if (!machine().side_effects_disabled() && !BIT(data, 1))
+ dma_stop();
+ break;
+
+ case 5:
+ data = m_scsi_read_callback(5);
+ if (!machine().side_effects_disabled())
+ {
+ if (!BIT(m_scsi_read_callback(2), 1))
+ dma_stop();
+ if (m_mode == mode::READ_WAIT_DRQ && BIT(data, 6))
+ {
+ m_mode = mode::READ_DMA;
+ m_read_fifo_data = u32(m_scsi_dma_read_callback(6)) << 24;
+ LOG("%s: Pseudo-DMA read started: first byte = %02X\n", machine().describe_context(), m_read_fifo_data >> 24);
+ m_read_fifo_bytes = 1;
+ m_pseudo_dma_timer->adjust(m_timeout);
+ m_cpu_halt_callback(ASSERT_LINE);
+ }
+ }
+ if ((m_mode == mode::READ_DMA && m_read_fifo_bytes != 0) || (m_mode == mode::WRITE_DMA && m_write_fifo_bytes < 4))
+ data |= 0x40;
+ break;
+
+ case 6:
+ if (!machine().side_effects_disabled() && !BIT(m_scsi_read_callback(2), 1))
+ dma_stop();
+ if (m_read_fifo_bytes != 0)
+ {
+ data = BIT(m_read_fifo_data, 24, 8);
+ if (!machine().side_effects_disabled())
+ {
+ --m_read_fifo_bytes;
+ LOG("%s: CPU read byte %02X from FIFO (%d left)\n", machine().describe_context(), data, m_read_fifo_bytes);
+ m_read_fifo_data <<= 8;
+ if (BIT(m_scsi_read_callback(5), 6))
+ read_fifo_process();
+ else if (!m_pseudo_dma_timer->enabled())
+ {
+ m_pseudo_dma_timer->adjust(m_timeout);
+ m_cpu_halt_callback(ASSERT_LINE);
+ }
+ }
+ }
+ else if (m_mode != mode::NON_DMA && pseudo_dma)
+ {
+ if (m_mode != mode::BAD_DMA)
+ {
+ logerror("%s: Read underflow on SCSI pseudo-DMA\n", machine().describe_context());
+ m_mode = mode::BAD_DMA;
+ }
+ m_timeout_error_callback(READ_ERROR);
+ m_pseudo_dma_timer->enable(false);
+ }
+ else
+ data = pseudo_dma ? m_scsi_dma_read_callback(6) : m_scsi_read_callback(6);
+ break;
+
+ default:
+ if (!machine().side_effects_disabled() && !BIT(m_scsi_read_callback(2), 1))
+ dma_stop();
+ data = m_scsi_read_callback(offset & 7);
+ break;
+ }
+
+ return data;
+}
+
+void mac_scsi_helper_device::write_wrapper(bool pseudo_dma, offs_t offset, u8 data)
+{
+ switch (offset & 7)
+ {
+ case 0:
+ if (m_mode == mode::BAD_DMA && pseudo_dma)
+ m_timeout_error_callback(WRITE_ERROR);
+ else if (m_mode == mode::WRITE_DMA && (m_write_fifo_bytes != 0 || !BIT(m_scsi_read_callback(5), 6)))
+ {
+ if (m_write_fifo_bytes < 4)
+ {
+ m_write_fifo_data = (m_write_fifo_data << 8) | data;
+ ++m_write_fifo_bytes;
+ logerror("%s: CPU writing byte %02X into FIFO (%d/4 filled)\n", machine().describe_context(), data, m_write_fifo_bytes);
+ if (!m_pseudo_dma_timer->enabled())
+ {
+ m_pseudo_dma_timer->adjust(m_timeout);
+ m_cpu_halt_callback(ASSERT_LINE);
+ }
+ }
+ else if (pseudo_dma)
+ {
+ logerror("%s: Write overflow on SCSI pseudo-DMA\n", machine().describe_context());
+ m_timeout_error_callback(WRITE_ERROR);
+ m_mode = mode::BAD_DMA;
+ }
+ }
+ else if (pseudo_dma)
+ m_scsi_dma_write_callback(0, data);
+ else
+ m_scsi_write_callback(0, data);
+ break;
+
+ case 2:
+ if (!BIT(data, 1))
+ dma_stop();
+ m_scsi_write_callback(2, data);
+ break;
+
+ case 5:
+ if (m_mode == mode::NON_DMA && BIT(m_scsi_read_callback(2), 1))
+ m_mode = mode::WRITE_DMA;
+ m_scsi_write_callback(5, data);
+ break;
+
+ case 6: case 7:
+ if (m_mode == mode::NON_DMA && BIT(m_scsi_read_callback(2), 1))
+ m_mode = mode::READ_WAIT_DRQ;
+ m_scsi_write_callback(offset & 7, data);
+ break;
+
+ default:
+ m_scsi_write_callback(offset & 7, data);
+ break;
+ }
+}
diff --git a/src/mame/machine/macscsi.h b/src/mame/machine/macscsi.h
new file mode 100644
index 00000000000..dcefbf494cf
--- /dev/null
+++ b/src/mame/machine/macscsi.h
@@ -0,0 +1,70 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#ifndef MAME_MACHINE_MACSCSI_H
+#define MAME_MACHINE_MACSCSI_H
+
+#pragma once
+
+class mac_scsi_helper_device : public device_t
+{
+public:
+ // device type constructor
+ mac_scsi_helper_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
+
+ // callback configuration
+ auto scsi_read_callback() { return m_scsi_read_callback.bind(); }
+ auto scsi_write_callback() { return m_scsi_write_callback.bind(); }
+ auto scsi_dma_read_callback() { return m_scsi_dma_read_callback.bind(); }
+ auto scsi_dma_write_callback() { return m_scsi_dma_write_callback.bind(); }
+ auto cpu_halt_callback() { return m_cpu_halt_callback.bind(); }
+ auto timeout_error_callback() { return m_timeout_error_callback.bind(); }
+
+ // miscellaneous configuration
+ void set_timeout(attotime timeout) { m_timeout = timeout; }
+
+ // read/write handlers
+ u8 read_wrapper(bool pseudo_dma, offs_t offset);
+ void write_wrapper(bool pseudo_dma, offs_t offset, u8 data);
+
+ DECLARE_WRITE_LINE_MEMBER(drq_w);
+
+protected:
+ // device-level overrides
+ virtual void device_resolve_objects() override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
+ enum class mode : u8 { NON_DMA, READ_WAIT_DRQ, READ_DMA, WRITE_DMA, BAD_DMA };
+
+ // internal helpers
+ void read_fifo_process();
+ void write_fifo_process();
+ TIMER_CALLBACK_MEMBER(timer_callback);
+ void dma_stop();
+
+ // callback objects
+ devcb_read8 m_scsi_read_callback;
+ devcb_write8 m_scsi_write_callback;
+ devcb_read8 m_scsi_dma_read_callback;
+ devcb_write8 m_scsi_dma_write_callback;
+ devcb_write_line m_cpu_halt_callback;
+ devcb_write8 m_timeout_error_callback;
+
+ // misc. parameters
+ attotime m_timeout;
+
+ // internal state
+ emu_timer *m_pseudo_dma_timer;
+ mode m_mode;
+ u8 m_read_fifo_bytes;
+ u8 m_write_fifo_bytes;
+ u32 m_read_fifo_data;
+ u32 m_write_fifo_data;
+};
+
+// device type declaration
+DECLARE_DEVICE_TYPE(MAC_SCSI_HELPER, mac_scsi_helper_device)
+
+#endif // MAME_MACHINE_MACSCSI_H