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)); + 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(*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)); + }); - NCR5380(config, m_ncr5380, C7M); - m_ncr5380->set_scsi_port("scsi"); - m_ncr5380->irq_callback().set(FUNC(mac_state::mac_scsi_irq)); + 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 m_via; optional_device m_macadb; required_device m_ram; - optional_device m_ncr5380; optional_device m_scsibus; + optional_device m_scsihelp; optional_device m_ncr5380n; required_device m_iwm; required_device_array 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("scsibus:7")->set_option_machine_config("ncr5380n", [this](device_t *device) { + ncr5380n_device &adapter = downcast(*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(*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 m_pmu; required_device m_via1; required_device m_macadb; - required_device m_ncr5380; + required_device m_ncr5380; + required_device m_scsihelp; required_device m_ram; required_device m_swim; required_device_array 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_ncr5380->ncr5380_write_reg(reg, data); + m_scsihelp->write_wrapper(pseudo_dma, 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)); + 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(*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)); + }); - NCR5380(config, m_ncr5380, C7M); - m_ncr5380->set_scsi_port("scsi"); + 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 m_via1; required_device m_via2; required_device m_macadb; - required_device m_ncr5380; + required_device m_ncr5380; + required_device m_scsihelp; required_device m_ram; required_device m_swim; required_device_array 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)); + 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(*device); + adapter.drq_handler().set(m_scsihelp, FUNC(mac_scsi_helper_device::drq_w)); + }); - NCR5380(config, m_ncr5380, C7M); - m_ncr5380->set_scsi_port("scsi"); + 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)); + 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(*device); + adapter.drq_handler().set(m_scsihelp, FUNC(mac_scsi_helper_device::drq_w)); + }); - NCR5380(config, m_ncr5380, C7M); - m_ncr5380->set_scsi_port("scsi"); + 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 m_macadb; required_device m_ram; required_device m_scc; - optional_device m_ncr5380; + required_device m_ncr5380; + required_device m_scsihelp; required_device m_fdc; required_device_array m_floppy; optional_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