From 88ea41b8879959f52a517b5b8ef136f50945f32f Mon Sep 17 00:00:00 2001 From: MooglyGuy Date: Tue, 10 Jan 2023 18:20:00 +0100 Subject: sun4c, SPARC, and NCR53C90 bug fixes: (#10821) [Ryan Holtz] * machine/ncr53c90.cpp: Renamed to ncr53c90 to avoid confusion about the actual NCR part name. * machine/ncr53c90.cpp: Fixed 'Select w/ ATN and Stop' command in DMA mode. * cpu/sparc: Avoid using temporary C-strings as address space names. * machine/sun4c_mmu.cpp: Fixed l2p debugger command by removing inadvertent narrowing conversion. * sun/sun4.cpp: Switched to NCR 53C90 from 53C90A, and fixed DMA byte-address masking - fixes Solaris 2.4 booting. --- scripts/src/machine.lua | 8 +- src/devices/bus/archimedes/podule/scsi_morley.cpp | 2 +- src/devices/bus/archimedes/podule/scsi_vti.cpp | 2 +- src/devices/bus/isa/bt54x.cpp | 2 +- src/devices/bus/isa/tekram_dc820.cpp | 2 +- src/devices/bus/isa/ultra14f.cpp | 2 +- src/devices/bus/isa/ultra24f.cpp | 2 +- src/devices/bus/nscsi/cdd2000.cpp | 2 +- src/devices/bus/nscsi/cdu415.h | 2 +- src/devices/bus/nscsi/cdu75s.h | 2 +- src/devices/bus/nscsi/crd254sh.h | 2 +- src/devices/bus/nscsi/cw7501.cpp | 2 +- src/devices/bus/qbus/qtx.h | 2 +- src/devices/cpu/sparc/sparc.cpp | 64 +- src/devices/cpu/sparc/sparc.h | 2 +- src/devices/machine/ncr5390.cpp | 1289 --------------------- src/devices/machine/ncr5390.h | 341 ------ src/devices/machine/ncr53c90.cpp | 1288 ++++++++++++++++++++ src/devices/machine/ncr53c90.h | 341 ++++++ src/devices/machine/spifi3.cpp | 2 +- src/devices/machine/spifi3.h | 4 +- src/devices/machine/sun4c_mmu.cpp | 21 +- src/mame/apple/macpdm.cpp | 2 +- src/mame/apple/macquadra700.cpp | 2 +- src/mame/dec/decstation.cpp | 2 +- src/mame/intergraph/interpro.cpp | 4 +- src/mame/microsoft/jazz.cpp | 2 +- src/mame/mips/mips.cpp | 2 +- src/mame/nec/ews4800.cpp | 2 +- src/mame/next/next.cpp | 12 +- src/mame/next/next.h | 8 +- src/mame/sun/sun4.cpp | 21 +- 32 files changed, 1712 insertions(+), 1729 deletions(-) delete mode 100644 src/devices/machine/ncr5390.cpp delete mode 100644 src/devices/machine/ncr5390.h create mode 100644 src/devices/machine/ncr53c90.cpp create mode 100644 src/devices/machine/ncr53c90.h diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua index 4439cfd339f..9a7ebb78b69 100644 --- a/scripts/src/machine.lua +++ b/scripts/src/machine.lua @@ -4034,13 +4034,13 @@ end --------------------------------------------------- -- ---@src/devices/machine/ncr5390.h,MACHINES["NCR5390"] = true +--@src/devices/machine/ncr53c90.h,MACHINES["NCR53C90"] = true --------------------------------------------------- -if (MACHINES["NCR5390"]~=null) then +if (MACHINES["NCR53C90"]~=null) then files { - MAME_DIR .. "src/devices/machine/ncr5390.cpp", - MAME_DIR .. "src/devices/machine/ncr5390.h", + MAME_DIR .. "src/devices/machine/ncr53c90.cpp", + MAME_DIR .. "src/devices/machine/ncr53c90.h", } end diff --git a/src/devices/bus/archimedes/podule/scsi_morley.cpp b/src/devices/bus/archimedes/podule/scsi_morley.cpp index 8e52766a6f4..438fc65dafa 100644 --- a/src/devices/bus/archimedes/podule/scsi_morley.cpp +++ b/src/devices/bus/archimedes/podule/scsi_morley.cpp @@ -15,7 +15,7 @@ #include "emu.h" #include "scsi_morley.h" #include "machine/7200fifo.h" -#include "machine/ncr5390.h" +#include "machine/ncr53c90.h" #include "bus/nscsi/devices.h" diff --git a/src/devices/bus/archimedes/podule/scsi_vti.cpp b/src/devices/bus/archimedes/podule/scsi_vti.cpp index f0239dfeeb0..a64bb3b6845 100644 --- a/src/devices/bus/archimedes/podule/scsi_vti.cpp +++ b/src/devices/bus/archimedes/podule/scsi_vti.cpp @@ -16,7 +16,7 @@ #include "scsi_vti.h" #include "machine/6522via.h" #include "machine/eepromser.h" -#include "machine/ncr5390.h" +#include "machine/ncr53c90.h" #include "bus/bbc/userport/userport.h" #include "bus/nscsi/devices.h" diff --git a/src/devices/bus/isa/bt54x.cpp b/src/devices/bus/isa/bt54x.cpp index 1c3c4bdf3f1..167dd415647 100644 --- a/src/devices/bus/isa/bt54x.cpp +++ b/src/devices/bus/isa/bt54x.cpp @@ -18,7 +18,7 @@ #include "bt54x.h" #include "bus/nscsi/devices.h" -#include "machine/ncr5390.h" +#include "machine/ncr53c90.h" //#include "machine/ncr86c05.h" DEFINE_DEVICE_TYPE(BT542B, bt542b_device, "bt542b", "BusTek BT-542B SCSI Host Adapter") // Rev. G or earlier diff --git a/src/devices/bus/isa/tekram_dc820.cpp b/src/devices/bus/isa/tekram_dc820.cpp index 56ffd8e4ccb..665e1642560 100644 --- a/src/devices/bus/isa/tekram_dc820.cpp +++ b/src/devices/bus/isa/tekram_dc820.cpp @@ -26,7 +26,7 @@ #include "bus/nscsi/devices.h" #include "cpu/i86/i186.h" #include "machine/i82355.h" -#include "machine/ncr5390.h" +#include "machine/ncr53c90.h" #include "machine/nscsi_bus.h" DEFINE_DEVICE_TYPE(TEKRAM_DC320B, tekram_dc320b_device, "dc320b", "Tekram DC-320B SCSI Controller") diff --git a/src/devices/bus/isa/ultra14f.cpp b/src/devices/bus/isa/ultra14f.cpp index f97b0acb54e..2dcb3652ec2 100644 --- a/src/devices/bus/isa/ultra14f.cpp +++ b/src/devices/bus/isa/ultra14f.cpp @@ -11,7 +11,7 @@ #include "bus/nscsi/devices.h" #include "cpu/m68000/m68008.h" -#include "machine/ncr5390.h" +#include "machine/ncr53c90.h" #include "machine/nscsi_bus.h" DEFINE_DEVICE_TYPE(ULTRA14F, ultra14f_device, "ultra14f", "Ultra-14F SCSI Host Adapter") diff --git a/src/devices/bus/isa/ultra24f.cpp b/src/devices/bus/isa/ultra24f.cpp index 211c1ab4b80..77d10fc0b67 100644 --- a/src/devices/bus/isa/ultra24f.cpp +++ b/src/devices/bus/isa/ultra24f.cpp @@ -11,7 +11,7 @@ #include "bus/nscsi/devices.h" #include "cpu/m68000/m68000.h" -#include "machine/ncr5390.h" +#include "machine/ncr53c90.h" #include "machine/nscsi_bus.h" DEFINE_DEVICE_TYPE(ULTRA24F, ultra24f_device, "ultra24f", "Ultra-24F SCSI Host Adapter") diff --git a/src/devices/bus/nscsi/cdd2000.cpp b/src/devices/bus/nscsi/cdd2000.cpp index 4a2e9c57811..60c5c72b97e 100644 --- a/src/devices/bus/nscsi/cdd2000.cpp +++ b/src/devices/bus/nscsi/cdd2000.cpp @@ -9,7 +9,7 @@ #include "emu.h" #include "bus/nscsi/cdd2000.h" #include "cpu/mc68hc11/mc68hc11.h" -#include "machine/ncr5390.h" +#include "machine/ncr53c90.h" DEFINE_DEVICE_TYPE(CDD2000, cdd2000_device, "cdd2000", "Philips CDD2000 CD-R") diff --git a/src/devices/bus/nscsi/cdu415.h b/src/devices/bus/nscsi/cdu415.h index 2874c69a8cf..5a35e62fffa 100644 --- a/src/devices/bus/nscsi/cdu415.h +++ b/src/devices/bus/nscsi/cdu415.h @@ -8,7 +8,7 @@ #include "machine/nscsi_bus.h" #include "cpu/h8/h83032.h" -#include "machine/ncr5390.h" +#include "machine/ncr53c90.h" class cdu415_device : public device_t, public nscsi_slot_card_interface { diff --git a/src/devices/bus/nscsi/cdu75s.h b/src/devices/bus/nscsi/cdu75s.h index b57550f9033..c034df923b4 100644 --- a/src/devices/bus/nscsi/cdu75s.h +++ b/src/devices/bus/nscsi/cdu75s.h @@ -8,7 +8,7 @@ #include "machine/nscsi_bus.h" #include "cpu/h8/h83032.h" -#include "machine/ncr5390.h" +#include "machine/ncr53c90.h" class cdu75s_device : public device_t, public nscsi_slot_card_interface { diff --git a/src/devices/bus/nscsi/crd254sh.h b/src/devices/bus/nscsi/crd254sh.h index c1ac2e4123d..20651a2ee85 100644 --- a/src/devices/bus/nscsi/crd254sh.h +++ b/src/devices/bus/nscsi/crd254sh.h @@ -8,7 +8,7 @@ #include "machine/nscsi_bus.h" #include "cpu/h8/h83042.h" -#include "machine/ncr5390.h" +#include "machine/ncr53c90.h" class crd254sh_device : public device_t, public nscsi_slot_card_interface { diff --git a/src/devices/bus/nscsi/cw7501.cpp b/src/devices/bus/nscsi/cw7501.cpp index c3ff2286f57..6e1af52e4d5 100644 --- a/src/devices/bus/nscsi/cw7501.cpp +++ b/src/devices/bus/nscsi/cw7501.cpp @@ -8,7 +8,7 @@ #include "emu.h" #include "bus/nscsi/cw7501.h" -#include "machine/ncr5390.h" +#include "machine/ncr53c90.h" DEFINE_DEVICE_TYPE(CW7501, cw7501_device, "cw7501", "Panasonic CW-7501 CD-R") DEFINE_DEVICE_TYPE(CDR4210, cdr4210_device, "cdr4210", "Creative Technology Blaster CD-R 4210") diff --git a/src/devices/bus/qbus/qtx.h b/src/devices/bus/qbus/qtx.h index 99c38f9f3ec..2357c0342e3 100644 --- a/src/devices/bus/qbus/qtx.h +++ b/src/devices/bus/qbus/qtx.h @@ -8,7 +8,7 @@ #include "qbus.h" #include "machine/mc68901.h" -#include "machine/ncr5390.h" +#include "machine/ncr53c90.h" //************************************************************************** diff --git a/src/devices/cpu/sparc/sparc.cpp b/src/devices/cpu/sparc/sparc.cpp index 4f1cb415739..e207c0837fe 100644 --- a/src/devices/cpu/sparc/sparc.cpp +++ b/src/devices/cpu/sparc/sparc.cpp @@ -59,8 +59,8 @@ DEFINE_DEVICE_TYPE(MB86930, mb86930_device, "mb86930", "Fujitsu MB86930 'SPARCli namespace { -const sparc_disassembler::asi_desc_map::value_type mb86930_asi_desc[] = { - +const sparc_disassembler::asi_desc_map::value_type mb86930_asi_desc[] = +{ { 0x01, { nullptr, "Control Registers" } }, { 0x02, { nullptr, "Instruction Cache Lock" } }, { 0x03, { nullptr, "Data Cache Lock" } }, @@ -73,7 +73,13 @@ const sparc_disassembler::asi_desc_map::value_type mb86930_asi_desc[] = { { 0x0e, { nullptr, "Data Cache Tag RAM" } }, { 0x0f, { nullptr, "Data Cache Data RAM" } } }; -} +} // anonymous namespace + +const char *const sparc_base_device::DEFAULT_ASI_NAMES[16] = +{ + "asi0", "asi1", "asi2", "asi3", "asi4", "asi5", "asi6", "asi7", + "asi8", "asi9", "asi10", "asi11", "asi12", "asi13", "asi14", "asi15" +}; //------------------------------------------------- // sparc_base_device - constructor @@ -89,8 +95,7 @@ sparc_base_device::sparc_base_device(const machine_config &mconfig, device_type { for (int i = 0; i < 0x10; i++) { - m_asi_names[i] = util::string_format("asi%x", i); - m_asi_config[i] = address_space_config(m_asi_names[i].c_str(), ENDIANNESS_BIG, 32, 32); + m_asi_config[i] = address_space_config(DEFAULT_ASI_NAMES[i], ENDIANNESS_BIG, 32, 32); } } } @@ -136,39 +141,22 @@ mb86930_device::mb86930_device(const machine_config &mconfig, const char *tag, d , m_cs_r(*this) , m_cs_w(*this) { - m_asi_names[0x00] = "debugger"; - m_asi_names[0x01] = "system_control"; - m_asi_names[0x02] = "icache_lock"; - m_asi_names[0x03] = "dcache_lock"; - m_asi_names[0x04] = "asi4"; - m_asi_names[0x05] = "asi5"; - m_asi_names[0x06] = "asi6"; - m_asi_names[0x07] = "asi7"; - m_asi_names[0x08] = "user_insn"; - m_asi_names[0x09] = "super_insn"; - m_asi_names[0x0a] = "user_data"; - m_asi_names[0x0b] = "super_data"; - m_asi_names[0x0c] = "icache_tag"; - m_asi_names[0x0d] = "icache_data"; - m_asi_names[0x0e] = "dcache_tag"; - m_asi_names[0x0f] = "dcache_data"; - - m_asi_config[0x00] = address_space_config(m_asi_names[0x00].c_str(), ENDIANNESS_BIG, 32, 32); - m_asi_config[0x01] = address_space_config(m_asi_names[0x01].c_str(), ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::control_map), this)); - m_asi_config[0x02] = address_space_config(m_asi_names[0x02].c_str(), ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::icache_lock_map), this)); - m_asi_config[0x03] = address_space_config(m_asi_names[0x03].c_str(), ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::dcache_lock_map), this)); - m_asi_config[0x04] = address_space_config(m_asi_names[0x04].c_str(), ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::mmu_map<4>), this)); - m_asi_config[0x05] = address_space_config(m_asi_names[0x05].c_str(), ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::mmu_map<5>), this)); - m_asi_config[0x06] = address_space_config(m_asi_names[0x06].c_str(), ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::mmu_map<6>), this)); - m_asi_config[0x07] = address_space_config(m_asi_names[0x07].c_str(), ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::mmu_map<7>), this)); - m_asi_config[0x08] = address_space_config(m_asi_names[0x08].c_str(), ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::mmu_map<8>), this)); - m_asi_config[0x09] = address_space_config(m_asi_names[0x09].c_str(), ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::mmu_map<9>), this)); - m_asi_config[0x0a] = address_space_config(m_asi_names[0x0a].c_str(), ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::mmu_map<10>), this)); - m_asi_config[0x0b] = address_space_config(m_asi_names[0x0b].c_str(), ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::mmu_map<11>), this)); - m_asi_config[0x0c] = address_space_config(m_asi_names[0x0c].c_str(), ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::icache_tag_map), this)); - m_asi_config[0x0d] = address_space_config(m_asi_names[0x0d].c_str(), ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::icache_data_map), this)); - m_asi_config[0x0e] = address_space_config(m_asi_names[0x0e].c_str(), ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::dcache_tag_map), this)); - m_asi_config[0x0f] = address_space_config(m_asi_names[0x0f].c_str(), ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::dcache_data_map), this)); + m_asi_config[0x00] = address_space_config("debugger", ENDIANNESS_BIG, 32, 32); + m_asi_config[0x01] = address_space_config("system_control", ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::control_map), this)); + m_asi_config[0x02] = address_space_config("icache_lock", ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::icache_lock_map), this)); + m_asi_config[0x03] = address_space_config("dcache_lock", ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::dcache_lock_map), this)); + m_asi_config[0x04] = address_space_config("asi4", ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::mmu_map<4>), this)); + m_asi_config[0x05] = address_space_config("asi5", ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::mmu_map<5>), this)); + m_asi_config[0x06] = address_space_config("asi6", ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::mmu_map<6>), this)); + m_asi_config[0x07] = address_space_config("asi7", ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::mmu_map<7>), this)); + m_asi_config[0x08] = address_space_config("user_insn", ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::mmu_map<8>), this)); + m_asi_config[0x09] = address_space_config("super_insn", ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::mmu_map<9>), this)); + m_asi_config[0x0a] = address_space_config("user_data", ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::mmu_map<10>), this)); + m_asi_config[0x0b] = address_space_config("super_data", ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::mmu_map<11>), this)); + m_asi_config[0x0c] = address_space_config("icache_tag", ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::icache_tag_map), this)); + m_asi_config[0x0d] = address_space_config("icache_data", ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::icache_data_map), this)); + m_asi_config[0x0e] = address_space_config("dcache_tag", ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::dcache_tag_map), this)); + m_asi_config[0x0f] = address_space_config("dcache_data", ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::dcache_data_map), this)); add_asi_desc([](sparc_disassembler *dasm) { dasm->add_asi_desc(mb86930_asi_desc); }); } diff --git a/src/devices/cpu/sparc/sparc.h b/src/devices/cpu/sparc/sparc.h index df1e531f3ea..5a3e1bd4c2d 100644 --- a/src/devices/cpu/sparc/sparc.h +++ b/src/devices/cpu/sparc/sparc.h @@ -155,7 +155,6 @@ protected: optional_device m_mmu; // address spaces - std::string m_asi_names[0x10]; address_space_config m_debugger_config; address_space_config m_asi_config[0x10]; memory_access<32, 2, 0, ENDIANNESS_BIG>::specific m_asi[0x20]; @@ -268,6 +267,7 @@ protected: #endif std::function m_asi_desc_adder; + static const char *const DEFAULT_ASI_NAMES[16]; }; class sparcv7_device : public sparc_base_device diff --git a/src/devices/machine/ncr5390.cpp b/src/devices/machine/ncr5390.cpp deleted file mode 100644 index 7a52d237982..00000000000 --- a/src/devices/machine/ncr5390.cpp +++ /dev/null @@ -1,1289 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Olivier Galibert - -/* - * TODO - * - 16 bit dma order, alignment and last byte handling - * - clean up variable naming and protection - */ - -#include "emu.h" -#include "ncr5390.h" - -#define LOG_GENERAL (1U << 0) -#define LOG_STATE (1U << 1) -#define LOG_FIFO (1U << 2) -#define LOG_COMMAND (1U << 3) - -#define VERBOSE (0) -#include "logmacro.h" - -#define DELAY_HACK - -DEFINE_DEVICE_TYPE(NCR5390, ncr5390_device, "ncr5390", "NCR 5390 SCSI Controller") -DEFINE_DEVICE_TYPE(NCR53C90A, ncr53c90a_device, "ncr53c90a", "NCR 53C90A Advanced SCSI Controller") -DEFINE_DEVICE_TYPE(NCR53C94, ncr53c94_device, "ncr53c94", "NCR 53C94 Advanced SCSI Controller") -DEFINE_DEVICE_TYPE(NCR53CF94, ncr53cf94_device, "ncr53cf94", "NCR 53CF94-2 Fast SCSI Controller") // TODO: differences not emulated - -void ncr5390_device::map(address_map &map) -{ - map(0x0, 0x0).rw(FUNC(ncr5390_device::tcounter_lo_r), FUNC(ncr5390_device::tcount_lo_w)); - map(0x1, 0x1).rw(FUNC(ncr5390_device::tcounter_hi_r), FUNC(ncr5390_device::tcount_hi_w)); - map(0x2, 0x2).rw(FUNC(ncr5390_device::fifo_r), FUNC(ncr5390_device::fifo_w)); - map(0x3, 0x3).rw(FUNC(ncr5390_device::command_r), FUNC(ncr5390_device::command_w)); - map(0x4, 0x4).rw(FUNC(ncr5390_device::status_r), FUNC(ncr5390_device::bus_id_w)); - map(0x5, 0x5).rw(FUNC(ncr5390_device::istatus_r), FUNC(ncr5390_device::timeout_w)); - map(0x6, 0x6).rw(FUNC(ncr5390_device::seq_step_r), FUNC(ncr5390_device::sync_period_w)); - map(0x7, 0x7).rw(FUNC(ncr5390_device::fifo_flags_r), FUNC(ncr5390_device::sync_offset_w)); - map(0x8, 0x8).rw(FUNC(ncr5390_device::conf_r), FUNC(ncr5390_device::conf_w)); - map(0xa, 0xa).w(FUNC(ncr5390_device::test_w)); - map(0x9, 0x9).w(FUNC(ncr5390_device::clock_w)); -} - -uint8_t ncr5390_device::read(offs_t offset) -{ - switch (offset) - { - case 0: return tcounter_lo_r(); - case 1: return tcounter_hi_r(); - case 2: return fifo_r(); - case 3: return command_r(); - case 4: return status_r(); - case 5: return istatus_r(); - case 6: return seq_step_r(); - case 7: return fifo_flags_r(); - case 8: return conf_r(); - default: return 0xff; - } -} - -void ncr5390_device::write(offs_t offset, uint8_t data) -{ - switch (offset) - { - case 0: tcount_lo_w(data); break; - case 1: tcount_hi_w(data); break; - case 2: fifo_w(data); break; - case 3: command_w(data); break; - case 4: bus_id_w(data); break; - case 5: timeout_w(data); break; - case 6: sync_period_w(data); break; - case 7: sync_offset_w(data); break; - case 8: conf_w(data); break; - case 9: clock_w(data); break; - case 10: test_w(data); break; - default: break; - } -} - -void ncr53c90a_device::map(address_map &map) -{ - ncr5390_device::map(map); - - map(0xb, 0xb).rw(FUNC(ncr53c90a_device::conf2_r), FUNC(ncr53c90a_device::conf2_w)); -} - -uint8_t ncr53c90a_device::read(offs_t offset) -{ - if (offset == 11) - return conf2_r(); - return ncr5390_device::read(offset); -} - -void ncr53c90a_device::write(offs_t offset, uint8_t data) -{ - if (offset == 11) - return conf2_w(data); - ncr5390_device::write(offset, data); -} - -void ncr53c94_device::map(address_map &map) -{ - ncr53c90a_device::map(map); - - map(0xc, 0xc).rw(FUNC(ncr53c94_device::conf3_r), FUNC(ncr53c94_device::conf3_w)); - map(0xf, 0xf).w(FUNC(ncr53c94_device::fifo_align_w)); -} - -uint8_t ncr53c94_device::read(offs_t offset) -{ - if (offset == 12) - return conf3_r(); - return ncr53c90a_device::read(offset); -} - -void ncr53c94_device::write(offs_t offset, uint8_t data) -{ - if (offset == 11) - conf3_w(data); - else if (offset == 15) - fifo_align_w(data); - else - ncr53c90a_device::write(offset, data); -} - -ncr5390_device::ncr5390_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) - : nscsi_device(mconfig, type, tag, owner, clock) - , nscsi_slot_card_interface(mconfig, *this, DEVICE_SELF) - , tm(nullptr), config(0), status(0), istatus(0), clock_conv(0), sync_offset(0), sync_period(0), bus_id(0) - , select_timeout(0), seq(0), tcount(0), tcounter(0), mode(0), fifo_pos(0), command_pos(0), state(0), xfr_phase(0), command_length(0), dma_dir(0), irq(false), drq(false), test_mode(false) - , m_irq_handler(*this) - , m_drq_handler(*this) -{ -} - -ncr53c90a_device::ncr53c90a_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) - : ncr5390_device(mconfig, type, tag, owner, clock) - , config2(0) -{ -} - -ncr5390_device::ncr5390_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : ncr5390_device(mconfig, NCR5390, tag, owner, clock) -{ -} - -ncr53c90a_device::ncr53c90a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : ncr53c90a_device(mconfig, NCR53C90A, tag, owner, clock) -{ -} - -ncr53c94_device::ncr53c94_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : ncr53c94_device(mconfig, NCR53C94, tag, owner, clock) -{ -} - -ncr53c94_device::ncr53c94_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) - : ncr53c90a_device(mconfig, type, tag, owner, clock) - , config3(0) - , m_busmd(BUSMD_0) -{ -} - -ncr53cf94_device::ncr53cf94_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : ncr53c94_device(mconfig, NCR53CF94, tag, owner, clock) -{ -} - -void ncr5390_device::device_start() -{ - nscsi_device::device_start(); - - save_item(NAME(command)); - save_item(NAME(config)); - save_item(NAME(status)); - save_item(NAME(istatus)); - save_item(NAME(clock_conv)); - save_item(NAME(sync_offset)); - save_item(NAME(sync_period)); - save_item(NAME(bus_id)); - save_item(NAME(select_timeout)); - save_item(NAME(seq)); - save_item(NAME(fifo)); - save_item(NAME(tcount)); - save_item(NAME(tcounter)); - save_item(NAME(mode)); - save_item(NAME(fifo_pos)); - save_item(NAME(command_pos)); - save_item(NAME(state)); - save_item(NAME(xfr_phase)); - save_item(NAME(command_length)); - save_item(NAME(dma_dir)); - save_item(NAME(irq)); - save_item(NAME(drq)); - save_item(NAME(test_mode)); - - m_irq_handler.resolve_safe(); - m_drq_handler.resolve_safe(); - - config = 0; - bus_id = 0; - select_timeout = 0; - tm = timer_alloc(FUNC(ncr5390_device::update_tick), this); -} - -void ncr5390_device::device_reset() -{ - fifo_pos = 0; - memset(fifo, 0, sizeof(fifo)); - - clock_conv = 2; - sync_period = 5; - sync_offset = 0; - seq = 0; - config &= 7; - status = 0; - istatus = 0; - irq = false; - m_irq_handler(irq); - - state = IDLE; - scsi_bus->ctrl_wait(scsi_refid, S_SEL|S_BSY|S_RST, S_ALL); - drq = false; - test_mode = false; - m_drq_handler(drq); - - scsi_bus->ctrl_w(scsi_refid, 0, S_RST); - tcount = 0; - tcounter = 0; - - reset_disconnect(); -} - -void ncr5390_device::reset_disconnect() -{ - scsi_bus->ctrl_w(scsi_refid, 0, ~S_RST); - - command_pos = 0; - command_length = 0; - memset(command, 0, sizeof(command)); - mode = MODE_D; -} - -void ncr5390_device::scsi_ctrl_changed() -{ - uint32_t ctrl = scsi_bus->ctrl_r(); - if(ctrl & S_RST) { - LOG("scsi bus reset\n"); - return; - } - - step(false); -} - -TIMER_CALLBACK_MEMBER(ncr5390_device::update_tick) -{ - step(true); -} - -void ncr5390_device::step(bool timeout) -{ - uint32_t ctrl = scsi_bus->ctrl_r(); - uint32_t data = scsi_bus->data_r(); - uint8_t c = command[0] & 0x7f; - - LOGMASKED(LOG_STATE, "state=%d.%d %s\n", - state & STATE_MASK, (state & SUB_MASK) >> SUB_SHIFT, - timeout ? "timeout" : "change"); - - if(mode == MODE_I && !(ctrl & S_BSY)) { - state = IDLE; - istatus |= I_DISCONNECT; - reset_disconnect(); - check_irq(); - } - switch(state & SUB_MASK ? state & SUB_MASK : state & STATE_MASK) { - case IDLE: - break; - - case BUSRESET_WAIT_INT: - state = IDLE; - scsi_bus->ctrl_w(scsi_refid, 0, S_RST); - reset_disconnect(); - - if (!(config & 0x40)) { - istatus |= I_SCSI_RESET; - check_irq(); - } - break; - - case ARB_COMPLETE << SUB_SHIFT: { - if(!timeout) - break; - - int win; - for(win=7; win>=0 && !(data & (1<data_w(scsi_refid, 0); - scsi_bus->ctrl_w(scsi_refid, 0, S_ALL); - fatalerror("ncr5390_device::step need to wait for bus free\n"); - } - state = (state & STATE_MASK) | (ARB_ASSERT_SEL << SUB_SHIFT); - scsi_bus->ctrl_w(scsi_refid, S_SEL, S_SEL); - delay(6); - break; - } - - case ARB_ASSERT_SEL << SUB_SHIFT: - if(!timeout) - break; - - scsi_bus->data_w(scsi_refid, (1<ctrl_w(scsi_refid, c == CD_SELECT_ATN || c == CD_SELECT_ATN_STOP ? S_ATN : 0, S_ATN|S_BSY); - delay(2); - break; - - case ARB_RELEASE_BUSY << SUB_SHIFT: - if(!timeout) - break; - - if(ctrl & S_BSY) { - state = (state & STATE_MASK) | (ARB_DESKEW_WAIT << SUB_SHIFT); - if(c == CD_RESELECT) - scsi_bus->ctrl_w(scsi_refid, S_BSY, S_BSY); - delay_cycles(2); - } else { - state = (state & STATE_MASK) | (ARB_TIMEOUT_BUSY << SUB_SHIFT); -#ifdef DELAY_HACK - delay(1); -#else - delay(8192*select_timeout); -#endif - } - break; - - case ARB_DESKEW_WAIT << SUB_SHIFT: - if(!timeout) - break; - - scsi_bus->data_w(scsi_refid, 0); - scsi_bus->ctrl_w(scsi_refid, 0, S_SEL); - - if(c == CD_RESELECT) { - LOG("mode switch to Target\n"); - mode = MODE_T; - } else { - LOG("mode switch to Initiator\n"); - mode = MODE_I; - } - state &= STATE_MASK; - step(true); - break; - - case ARB_TIMEOUT_BUSY << SUB_SHIFT: - if(timeout) { - scsi_bus->data_w(scsi_refid, 0); - LOG("select timeout\n"); - state = (state & STATE_MASK) | (ARB_TIMEOUT_ABORT << SUB_SHIFT); - delay(1000); - } else if(ctrl & S_BSY) { - state = (state & STATE_MASK) | (ARB_DESKEW_WAIT << SUB_SHIFT); - if(c == CD_RESELECT) - scsi_bus->ctrl_w(scsi_refid, S_BSY, S_BSY); - delay_cycles(2); - } - break; - - case ARB_TIMEOUT_ABORT << SUB_SHIFT: - if(!timeout) - break; - - if(ctrl & S_BSY) { - state = (state & STATE_MASK) | (ARB_DESKEW_WAIT << SUB_SHIFT); - if(c == CD_RESELECT) - scsi_bus->ctrl_w(scsi_refid, S_BSY, S_BSY); - delay_cycles(2); - } else { - scsi_bus->ctrl_w(scsi_refid, 0, S_ALL); - state = IDLE; - istatus |= I_DISCONNECT; - reset_disconnect(); - check_irq(); - } - break; - - case SEND_WAIT_SETTLE << SUB_SHIFT: - if(!timeout) - break; - - state = (state & STATE_MASK) | (SEND_WAIT_REQ_0 << SUB_SHIFT); - step(false); - break; - - case SEND_WAIT_REQ_0 << SUB_SHIFT: - if(ctrl & S_REQ) - break; - state = state & STATE_MASK; - scsi_bus->data_w(scsi_refid, 0); - scsi_bus->ctrl_w(scsi_refid, 0, S_ACK); - step(false); - break; - - case RECV_WAIT_REQ_1 << SUB_SHIFT: - if(!(ctrl & S_REQ)) - break; - - state = (state & STATE_MASK) | (RECV_WAIT_SETTLE << SUB_SHIFT); - delay_cycles(sync_period); - break; - - case RECV_WAIT_SETTLE << SUB_SHIFT: - if(!timeout) - break; - - if((state & STATE_MASK) != INIT_XFR_RECV_PAD) - fifo_push(scsi_bus->data_r()); - scsi_bus->ctrl_w(scsi_refid, S_ACK, S_ACK); - state = (state & STATE_MASK) | (RECV_WAIT_REQ_0 << SUB_SHIFT); - step(false); - break; - - case RECV_WAIT_REQ_0 << SUB_SHIFT: - if(ctrl & S_REQ) - break; - state = state & STATE_MASK; - step(false); - break; - - case DISC_SEL_ARBITRATION_INIT: - // wait until a command is in the fifo - if (!fifo_pos) { - // dma starts after bus arbitration/selection is complete - check_drq(); - break; - } - - command_length = fifo_pos + tcounter; - state = DISC_SEL_ARBITRATION; - step(false); - break; - - case DISC_SEL_ARBITRATION: - if(c == CD_SELECT) { - state = DISC_SEL_WAIT_REQ; - } else - state = DISC_SEL_ATN_WAIT_REQ; - - scsi_bus->ctrl_wait(scsi_refid, S_REQ, S_REQ); - if(ctrl & S_REQ) - step(false); - break; - - case DISC_SEL_ATN_WAIT_REQ: - if(!(ctrl & S_REQ)) - break; - if((ctrl & S_PHASE_MASK) != S_PHASE_MSG_OUT) { - function_complete(); - break; - } - if(c == CD_SELECT_ATN) - scsi_bus->ctrl_w(scsi_refid, 0, S_ATN); - state = DISC_SEL_ATN_SEND_BYTE; - send_byte(); - break; - - case DISC_SEL_ATN_SEND_BYTE: - command_length--; - if(c == CD_SELECT_ATN_STOP) { - seq = 1; - function_bus_complete(); - } else { - state = DISC_SEL_WAIT_REQ; - } - break; - - case DISC_SEL_WAIT_REQ: - if(!(ctrl & S_REQ)) - break; - if((ctrl & S_PHASE_MASK) != S_PHASE_COMMAND) { - if(!command_length) - seq = 4; - else - seq = 2; - scsi_bus->ctrl_wait(scsi_refid, 0, S_REQ); - function_bus_complete(); - break; - } - if(seq < 3) - seq = 3; - state = DISC_SEL_SEND_BYTE; - send_byte(); - break; - - case DISC_SEL_SEND_BYTE: - if(command_length) { - command_length--; - if(!command_length) - seq = 4; - } - - state = DISC_SEL_WAIT_REQ; - break; - - case INIT_CPT_RECV_BYTE_ACK: - state = INIT_CPT_RECV_WAIT_REQ; - scsi_bus->ctrl_w(scsi_refid, 0, S_ACK); - break; - - case INIT_CPT_RECV_WAIT_REQ: - if(!(ctrl & S_REQ)) - break; - - if((ctrl & S_PHASE_MASK) != S_PHASE_MSG_IN) { - command_pos = 0; - bus_complete(); - } else { - state = INIT_CPT_RECV_BYTE_NACK; - recv_byte(); - } - break; - - case INIT_CPT_RECV_BYTE_NACK: - function_complete(); - break; - - case INIT_MSG_WAIT_REQ: - if((ctrl & (S_REQ|S_BSY)) == S_BSY) - break; - bus_complete(); - break; - - case INIT_XFR: - switch(xfr_phase) { - case S_PHASE_DATA_OUT: - case S_PHASE_COMMAND: - case S_PHASE_MSG_OUT: - state = INIT_XFR_SEND_BYTE; - - // can't send if the fifo is empty - if (fifo_pos == 0) - break; - - // if it's the last message byte, deassert ATN before sending - if (xfr_phase == S_PHASE_MSG_OUT && ((!dma_command && fifo_pos == 1) || (dma_command && tcounter == 1))) - scsi_bus->ctrl_w(scsi_refid, 0, S_ATN); - - send_byte(); - break; - - case S_PHASE_DATA_IN: - case S_PHASE_STATUS: - case S_PHASE_MSG_IN: - // can't receive if the fifo is full - if (fifo_pos == 16) - break; - - // if it's the last message byte, ACK remains asserted, terminate with function_complete() - state = (xfr_phase == S_PHASE_MSG_IN && (!dma_command || tcounter == 1)) ? INIT_XFR_RECV_BYTE_NACK : INIT_XFR_RECV_BYTE_ACK; - - recv_byte(); - break; - - default: - LOG("xfer on phase %d\n", scsi_bus->ctrl_r() & S_PHASE_MASK); - function_complete(); - break; - } - break; - - case INIT_XFR_WAIT_REQ: - if(!(ctrl & S_REQ)) - break; - - // check for command complete - if ((dma_command && (status & S_TC0) && (dma_dir == DMA_IN || fifo_pos == 0)) // dma in/out: transfer count == 0 - || (!dma_command && (xfr_phase & S_INP) == 0 && fifo_pos == 0) // non-dma out: fifo empty - || (!dma_command && (xfr_phase & S_INP) == S_INP && fifo_pos == 1)) // non-dma in: every byte - state = INIT_XFR_BUS_COMPLETE; - else - // check for phase change - if((ctrl & S_PHASE_MASK) != xfr_phase) { - command_pos = 0; - state = INIT_XFR_BUS_COMPLETE; - } else { - state = INIT_XFR; - } - step(false); - break; - - case INIT_XFR_SEND_BYTE: - state = INIT_XFR_WAIT_REQ; - step(false); - break; - - case INIT_XFR_RECV_BYTE_ACK: - state = INIT_XFR_WAIT_REQ; - scsi_bus->ctrl_w(scsi_refid, 0, S_ACK); - break; - - case INIT_XFR_RECV_BYTE_NACK: - state = INIT_XFR_FUNCTION_COMPLETE; - step(false); - break; - - case INIT_XFR_FUNCTION_COMPLETE: - // wait for dma transfer to complete or fifo to drain - if (dma_command && !(status & S_TC0) && fifo_pos) - break; - - function_complete(); - break; - - case INIT_XFR_BUS_COMPLETE: - // wait for dma transfer to complete or fifo to drain - if (dma_command && !(status & S_TC0) && fifo_pos) - break; - - bus_complete(); - break; - - case INIT_XFR_SEND_PAD_WAIT_REQ: - if(!(ctrl & S_REQ)) - break; - - if((ctrl & S_PHASE_MASK) != xfr_phase) { - command_pos = 0; - bus_complete(); - } else { - state = INIT_XFR_SEND_PAD; - send_byte(); - } - break; - - case INIT_XFR_SEND_PAD: - decrement_tcounter(); - if(!(status & S_TC0)) { - state = INIT_XFR_SEND_PAD_WAIT_REQ; - step(false); - } else - function_complete(); - break; - - case INIT_XFR_RECV_PAD_WAIT_REQ: - if(!(ctrl & S_REQ)) - break; - - if((ctrl & S_PHASE_MASK) != xfr_phase) { - command_pos = 0; - bus_complete(); - } else { - state = INIT_XFR_RECV_PAD; - recv_byte(); - } - break; - - case INIT_XFR_RECV_PAD: - decrement_tcounter(); - if(!(status & S_TC0)) { - state = INIT_XFR_RECV_PAD_WAIT_REQ; - scsi_bus->ctrl_w(scsi_refid, 0, S_ACK); - step(false); - } else - function_complete(); - break; - - default: - LOG("step() unexpected state %d.%d\n", - state & STATE_MASK, (state & SUB_MASK) >> SUB_SHIFT); - exit(0); - } -} - -void ncr5390_device::send_byte() -{ - if(!fifo_pos) - fatalerror("ncr5390_device::send_byte - !fifo_pos\n"); - - state = (state & STATE_MASK) | (SEND_WAIT_SETTLE << SUB_SHIFT); - if((state & STATE_MASK) != INIT_XFR_SEND_PAD && - ((state & STATE_MASK) != DISC_SEL_SEND_BYTE || - command_length)) - scsi_bus->data_w(scsi_refid, fifo_pop()); - else - scsi_bus->data_w(scsi_refid, 0); - - scsi_bus->ctrl_w(scsi_refid, S_ACK, S_ACK); - scsi_bus->ctrl_wait(scsi_refid, S_REQ, S_REQ); - delay_cycles(sync_period); -} - -void ncr5390_device::recv_byte() -{ - scsi_bus->ctrl_wait(scsi_refid, S_REQ, S_REQ); - state = (state & STATE_MASK) | (RECV_WAIT_REQ_1 << SUB_SHIFT); - step(false); -} - -void ncr5390_device::function_bus_complete() -{ - LOG("function_bus_complete\n"); - state = IDLE; - istatus |= I_FUNCTION|I_BUS; - dma_set(DMA_NONE); - check_drq(); - check_irq(); -} - -void ncr5390_device::function_complete() -{ - LOG("function_complete\n"); - state = IDLE; - istatus |= I_FUNCTION; - dma_set(DMA_NONE); - check_drq(); - check_irq(); -} - -void ncr5390_device::bus_complete() -{ - LOG("bus_complete\n"); - state = IDLE; - istatus |= I_BUS; - dma_set(DMA_NONE); - check_drq(); - check_irq(); -} - -void ncr5390_device::delay(int cycles) -{ - if(!clock_conv) - return; - cycles *= clock_conv; - tm->adjust(clocks_to_attotime(cycles)); -} - -void ncr5390_device::delay_cycles(int cycles) -{ - tm->adjust(clocks_to_attotime(cycles)); -} - -uint8_t ncr5390_device::tcounter_lo_r() -{ - LOG("tcounter_lo_r %02x (%s)\n", tcounter & 0xff, machine().describe_context()); - return tcounter; -} - -void ncr5390_device::tcount_lo_w(uint8_t data) -{ - tcount = (tcount & 0xff00) | data; - LOG("tcount_lo_w %02x (%s)\n", data, machine().describe_context()); -} - -uint8_t ncr5390_device::tcounter_hi_r() -{ - LOG("tcounter_hi_r %02x (%s)\n", tcounter >> 8, machine().describe_context()); - return tcounter >> 8; -} - -void ncr5390_device::tcount_hi_w(uint8_t data) -{ - tcount = (tcount & 0x00ff) | (data << 8); - LOG("tcount_hi_w %02x (%s)\n", data, machine().describe_context()); -} - -uint8_t ncr5390_device::fifo_pop() -{ - uint8_t r = fifo[0]; - fifo_pos--; - memmove(fifo, fifo+1, fifo_pos); - check_drq(); - return r; -} - -void ncr5390_device::fifo_push(uint8_t val) -{ - fifo[fifo_pos++] = val; - check_drq(); -} - -uint8_t ncr5390_device::fifo_r() -{ - uint8_t r; - if(fifo_pos) { - r = fifo[0]; - fifo_pos--; - memmove(fifo, fifo+1, fifo_pos); - } else - r = 0; - LOGMASKED(LOG_FIFO, "fifo_r 0x%02x fifo_pos %d (%s)\n", r, fifo_pos, machine().describe_context()); - return r; -} - -void ncr5390_device::fifo_w(uint8_t data) -{ - LOGMASKED(LOG_FIFO, "fifo_w 0x%02x fifo_pos %d (%s)\n", data, fifo_pos, machine().describe_context()); - if(fifo_pos != 16) - fifo[fifo_pos++] = data; -} - -uint8_t ncr5390_device::command_r() -{ - LOG("command_r (%s)\n", machine().describe_context()); - return command[0]; -} - -void ncr5390_device::command_w(uint8_t data) -{ - LOG("command_w %02x command_pos %d (%s)\n", data, command_pos, machine().describe_context()); - if(command_pos == 2) { - status |= S_GROSS_ERROR; - check_irq(); - return; - } - /* - * Note the RESET chip and RESET SCSI Bus commands execute as soon as they are loaded into - * the top of the Command Register. - */ - if((data & 0x7f) == CM_RESET || (data & 0x7f) == CM_RESET_BUS) - command_pos = 0; - - command[command_pos++] = data; - if(command_pos == 1) - start_command(); -} - -void ncr5390_device::command_pop_and_chain() -{ - if(command_pos) { - command_pos--; - if(command_pos) { - command[0] = command[1]; - start_command(); - } - } -} - -void ncr5390_device::start_command() -{ - uint8_t c = command[0] & 0x7f; - if(!check_valid_command(c)) { - LOG("invalid command %02x\n", command[0]); - istatus |= I_ILLEGAL; - check_irq(); - return; - } - - // for dma commands, reload transfer counter - dma_command = command[0] & 0x80; - if (dma_command) - { - tcounter = tcount; - - // clear transfer count zero flag when counter is reloaded - status &= ~S_TC0; - } - else - tcounter = 0; - - switch(c) { - case CM_NOP: - LOGMASKED(LOG_COMMAND, "NOP\n"); - command_pop_and_chain(); - break; - - case CM_FLUSH_FIFO: - LOGMASKED(LOG_COMMAND, "Flush FIFO\n"); - fifo_pos = 0; - command_pop_and_chain(); - break; - - case CM_RESET: - LOGMASKED(LOG_COMMAND, "Reset chip\n"); - device_reset(); - break; - - case CM_RESET_BUS: - LOGMASKED(LOG_COMMAND, "Reset SCSI bus\n"); - state = BUSRESET_WAIT_INT; - scsi_bus->ctrl_w(scsi_refid, S_RST, S_RST); - delay(130); - break; - - case CD_RESELECT: - LOGMASKED(LOG_COMMAND, "Reselect sequence\n"); - state = DISC_REC_ARBITRATION; - arbitrate(); - break; - - case CD_SELECT: - case CD_SELECT_ATN: - case CD_SELECT_ATN_STOP: - LOGMASKED(LOG_COMMAND, - (c == CD_SELECT) ? "Select without ATN sequence\n" : - (c == CD_SELECT_ATN) ? "Select with ATN sequence\n" : - "Select with ATN and stop sequence\n"); - seq = 0; - state = DISC_SEL_ARBITRATION_INIT; - dma_set(dma_command ? DMA_OUT : DMA_NONE); - arbitrate(); - break; - - case CD_ENABLE_SEL: - LOGMASKED(LOG_COMMAND, "Enable selection/reselection\n"); - command_pop_and_chain(); - break; - - case CD_DISABLE_SEL: - LOGMASKED(LOG_COMMAND, "Disable selection/reselection\n"); - command_pop_and_chain(); - break; - - case CI_XFER: - LOGMASKED(LOG_COMMAND, "Transfer information\n"); - state = INIT_XFR; - xfr_phase = scsi_bus->ctrl_r() & S_PHASE_MASK; - dma_set(dma_command ? ((xfr_phase & S_INP) ? DMA_IN : DMA_OUT) : DMA_NONE); - check_drq(); - step(false); - break; - - case CI_COMPLETE: - LOGMASKED(LOG_COMMAND, "Initiator command complete sequence\n"); - state = INIT_CPT_RECV_BYTE_ACK; - dma_set(dma_command ? DMA_IN : DMA_NONE); - recv_byte(); - break; - - case CI_MSG_ACCEPT: - LOGMASKED(LOG_COMMAND, "Message accepted\n"); - state = INIT_MSG_WAIT_REQ; - // It's undocumented what the sequence register should contain after a message accept - // command, but the InterPro boot code expects it to be non-zero; setting it to an - // arbirary 1 here makes InterPro happy. Also in the InterPro case (perhaps typical), - // after ACK is asserted the device disconnects and the INIT_MSG_WAIT_REQ state is never - // entered, meaning we end up with I_DISCONNECT instead of I_BUS interrupt status. - seq = 1; - scsi_bus->ctrl_w(scsi_refid, 0, S_ACK); - step(false); - break; - - case CI_PAD: - LOGMASKED(LOG_COMMAND, "Transfer pad\n"); - xfr_phase = scsi_bus->ctrl_r() & S_PHASE_MASK; - if(xfr_phase & S_INP) - state = INIT_XFR_RECV_PAD_WAIT_REQ; - else - state = INIT_XFR_SEND_PAD_WAIT_REQ; - scsi_bus->ctrl_w(scsi_refid, 0, S_ACK); - step(false); - break; - - case CI_SET_ATN: - LOGMASKED(LOG_COMMAND, "Set ATN\n"); - scsi_bus->ctrl_w(scsi_refid, S_ATN, S_ATN); - command_pop_and_chain(); - break; - - case CI_RESET_ATN: - LOGMASKED(LOG_COMMAND, "Reset ATN\n"); - scsi_bus->ctrl_w(scsi_refid, 0, S_ATN); - command_pop_and_chain(); - break; - - default: - fatalerror("ncr5390_device::start_command unimplemented command %02x\n", c); - } -} - -bool ncr5390_device::check_valid_command(uint8_t cmd) -{ - int subcmd = cmd & 15; - switch((cmd >> 4) & 7) { - case 0: return subcmd <= 3; - case 4: return mode == MODE_D && subcmd <= 5; - case 2: return mode == MODE_T && subcmd <= 11 && subcmd != 6; - case 1: return mode == MODE_I && (subcmd <= 2 || subcmd == 8 || subcmd == 10); - } - return false; -} - -void ncr5390_device::arbitrate() -{ - state = (state & STATE_MASK) | (ARB_COMPLETE << SUB_SHIFT); - scsi_bus->data_w(scsi_refid, 1 << scsi_id); - scsi_bus->ctrl_w(scsi_refid, S_BSY, S_BSY); - delay(11); -} - -void ncr5390_device::check_irq() -{ - bool oldirq = irq; - irq = istatus != 0; - if(irq != oldirq) - m_irq_handler(irq); - -} - -uint8_t ncr5390_device::status_r() -{ - uint32_t ctrl = scsi_bus->ctrl_r(); - uint8_t res = status | (ctrl & S_MSG ? 4 : 0) | (ctrl & S_CTL ? 2 : 0) | (ctrl & S_INP ? 1 : 0); - LOG("status_r %02x (%s)\n", res, machine().describe_context()); - - return res; -} - -void ncr5390_device::bus_id_w(uint8_t data) -{ - bus_id = data & 7; - LOG("bus_id=%d\n", bus_id); -} - -uint8_t ncr5390_device::istatus_r() -{ - uint8_t res = istatus; - - if (irq) - { - status &= ~(S_GROSS_ERROR | S_PARITY | S_TCC); - istatus = 0; - seq = 0; - } - check_irq(); - if(res) - command_pop_and_chain(); - - LOG("istatus_r %02x (%s)\n", res, machine().describe_context()); - return res; -} - -void ncr5390_device::timeout_w(uint8_t data) -{ - LOG("timeout_w 0x%02x\n", data); - select_timeout = data; -} - -uint8_t ncr5390_device::seq_step_r() -{ - LOG("seq_step_r %d (%s)\n", seq, machine().describe_context()); - return seq; -} - -void ncr5390_device::sync_period_w(uint8_t data) -{ - sync_period = data & 0x1f; -} - -uint8_t ncr5390_device::fifo_flags_r() -{ - return fifo_pos; -} - -void ncr5390_device::sync_offset_w(uint8_t data) -{ - sync_offset = data & 0x0f; -} - -uint8_t ncr5390_device::conf_r() -{ - return config; -} - -void ncr5390_device::conf_w(uint8_t data) -{ - config = data; - scsi_id = data & 7; - - // test mode can only be cleared by hard/soft reset - if (data & 0x8) - test_mode = true; -} - -void ncr5390_device::test_w(uint8_t data) -{ - if (test_mode) - logerror("test_w %d (%s) - test mode not implemented\n", data, machine().describe_context()); -} - -void ncr5390_device::clock_w(uint8_t data) -{ - clock_conv = data & 0x07; -} - -void ncr5390_device::dma_set(int dir) -{ - dma_dir = dir; - - // account for data already in the fifo - if (dir == DMA_OUT && fifo_pos) - decrement_tcounter(fifo_pos); -} - -void ncr5390_device::dma_w(uint8_t val) -{ - fifo_push(val); - decrement_tcounter(); - check_drq(); - step(false); -} - -uint8_t ncr5390_device::dma_r() -{ - uint8_t r = fifo_pop(); - decrement_tcounter(); - check_drq(); - step(false); - return r; -} - -void ncr5390_device::check_drq() -{ - bool drq_state = drq; - - switch (dma_dir) { - case DMA_NONE: - drq_state = false; - break; - - case DMA_IN: // device to memory - drq_state = !(status & S_TC0) && fifo_pos; - break; - - case DMA_OUT: // memory to device - drq_state = !(status & S_TC0) && fifo_pos < 16; - break; - } - - if (drq_state != drq) { - drq = drq_state; - m_drq_handler(drq); - } -} - -void ncr5390_device::decrement_tcounter(int count) -{ - if (!dma_command) - return; - - tcounter -= count; - if (tcounter == 0) - status |= S_TC0; -} - -/* - * According to the NCR 53C90A, 53C90B data book (http://bitsavers.org/pdf/ncr/scsi/NCR53C90ab.pdf), - * the following are the differences from the 53C90: - * - * - Supports three-byte message exchange SCSI-2 tagged queueing - * - Added select with ATN3 command - * - Added target DMA abort command - * - Added interrupt polling bit - * - Added second configuration register - * - Improved immunity to cable impedance mismatches and improper termination - * - Tri-state DMA request output - * - Cut leakage current on SCSI input pins when powered off - * - Relaxed register timings - * - Relaxed DMA timings - * - Relaxed CLK duty cycle - * - Lengthened read data access time - * - NOP required less often - */ - -void ncr53c90a_device::device_start() -{ - save_item(NAME(config2)); - - config2 = 0; - - ncr5390_device::device_start(); -} - -void ncr53c90a_device::device_reset() -{ - config2 = 0; - - ncr5390_device::device_reset(); -} - -uint8_t ncr53c90a_device::status_r() -{ - uint32_t ctrl = scsi_bus->ctrl_r(); - uint8_t res = (irq ? S_INTERRUPT : 0) | status | (ctrl & S_MSG ? 4 : 0) | (ctrl & S_CTL ? 2 : 0) | (ctrl & S_INP ? 1 : 0); - LOG("status_r %02x (%s)\n", res, machine().describe_context()); - if (irq) - status &= ~(S_GROSS_ERROR | S_PARITY | S_TCC); - return res; -} - -bool ncr53c90a_device::check_valid_command(uint8_t cmd) -{ - int subcmd = cmd & 15; - switch ((cmd >> 4) & 7) { - case 0: return subcmd <= 3 || (mode == MODE_T && subcmd == 4); - case 4: return mode == MODE_D && subcmd <= 6; - case 2: return mode == MODE_T && subcmd <= 11 && subcmd != 6; - case 1: return mode == MODE_I && (subcmd <= 2 || subcmd == 8 || subcmd == 10 || subcmd == 11); - } - return false; -} - -void ncr53c94_device::device_start() -{ - save_item(NAME(config3)); - - config3 = 0; - - ncr53c90a_device::device_start(); -} - -void ncr53c94_device::device_reset() -{ - config3 = 0; - - ncr53c90a_device::device_reset(); -} - -u16 ncr53c94_device::dma16_r() -{ - // check fifo underflow - if (fifo_pos < 2) - fatalerror("ncr53c94_device::dma16_r fifo_pos %d\n", fifo_pos); - - // pop two bytes from fifo - u16 const data = (fifo[0] << 8) | fifo[1]; - fifo_pos -= 2; - memmove(fifo, fifo + 2, fifo_pos); - - // update drq - decrement_tcounter(2); - check_drq(); - - step(false); - - return data; -} - -void ncr53c94_device::dma16_w(u16 data) -{ - // check fifo overflow - if (fifo_pos > 14) - fatalerror("ncr53c94_device::dma16_w fifo_pos %d\n", fifo_pos); - - // push two bytes into fifo - fifo[fifo_pos++] = data >> 8; - fifo[fifo_pos++] = data; - - // update drq - decrement_tcounter(2); - check_drq(); - - step(false); -} - -void ncr53c94_device::check_drq() -{ - if (m_busmd != BUSMD_0) - { - bool drq_state = drq; - - switch (dma_dir) { - case DMA_NONE: - drq_state = false; - break; - - case DMA_IN: // device to memory - drq_state = !(status & S_TC0) && fifo_pos > 1; - break; - - case DMA_OUT: // memory to device - drq_state = !(status & S_TC0) && fifo_pos < 15; - break; - } - - if (drq_state != drq) { - drq = drq_state; - m_drq_handler(drq); - } - } - else - ncr5390_device::check_drq(); -} diff --git a/src/devices/machine/ncr5390.h b/src/devices/machine/ncr5390.h deleted file mode 100644 index ba38e1b52cf..00000000000 --- a/src/devices/machine/ncr5390.h +++ /dev/null @@ -1,341 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Olivier Galibert -#ifndef MAME_MACHINE_NCR5390_H -#define MAME_MACHINE_NCR5390_H - -#pragma once - -#include "machine/nscsi_bus.h" - -class ncr5390_device : public nscsi_device, public nscsi_slot_card_interface -{ -public: - ncr5390_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - // configuration helpers - auto irq_handler_cb() { return m_irq_handler.bind(); } - auto drq_handler_cb() { return m_drq_handler.bind(); } - - virtual void map(address_map &map); - - uint8_t tcounter_lo_r(); - void tcount_lo_w(uint8_t data); - uint8_t tcounter_hi_r(); - void tcount_hi_w(uint8_t data); - uint8_t fifo_r(); - void fifo_w(uint8_t data); - uint8_t command_r(); - void command_w(uint8_t data); - virtual uint8_t status_r(); - void bus_id_w(uint8_t data); - uint8_t istatus_r(); - void timeout_w(uint8_t data); - uint8_t seq_step_r(); - void sync_period_w(uint8_t data); - uint8_t fifo_flags_r(); - void sync_offset_w(uint8_t data); - uint8_t conf_r(); - void conf_w(uint8_t data); - void test_w(uint8_t data); - void clock_w(uint8_t data); - - virtual uint8_t read(offs_t offset); - virtual void write(offs_t offset, uint8_t data); - - virtual void scsi_ctrl_changed() override; - - uint8_t dma_r(); - void dma_w(uint8_t val); - -protected: - ncr5390_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); - - virtual void device_start() override; - virtual void device_reset() override; - - TIMER_CALLBACK_MEMBER(update_tick); - - enum { MODE_D, MODE_T, MODE_I }; - enum { IDLE }; - - enum { - // Bus initiated sequences - BUSINIT_SETTLE_DELAY = 1, - BUSINIT_ASSERT_BUS_SEL, - BUSINIT_MSG_OUT, - BUSINIT_RECV_BYTE, - BUSINIT_ASSERT_BUS_RESEL, - BUSINIT_WAIT_REQ, - BUSINIT_RECV_BYTE_NACK, - - // Bus SCSI Reset - BUSRESET_WAIT_INT, - BUSRESET_RESET_BOARD, - - // Disconnected state commands - DISC_SEL_ARBITRATION_INIT, - DISC_SEL_ARBITRATION, - DISC_SEL_ATN_WAIT_REQ, - DISC_SEL_ATN_SEND_BYTE, - DISC_SEL_WAIT_REQ, - DISC_SEL_SEND_BYTE, - DISC_REC_ARBITRATION, - DISC_REC_MSG_IN, - DISC_REC_SEND_BYTE, - DISC_RESET, - - // Command sequence - CMDSEQ_CMD_PHASE, - CMDSEQ_RECV_BYTE, - - // Target commands - TARGET_SEND_BYTE, - TARGET_CMD_RECV_BYTE, - TARGET_MSG_RECV_BYTE, - TARGET_MSG_RECV_PAD, - TARGET_DISC_SEND_BYTE, - TARGET_DISC_MSG_IN, - TARGET_DISC_SEND_BYTE_2, - - // Initiator commands - INIT_MSG_WAIT_REQ, - INIT_XFR, - INIT_XFR_SEND_BYTE, - INIT_XFR_SEND_PAD_WAIT_REQ, - INIT_XFR_SEND_PAD, - INIT_XFR_RECV_PAD_WAIT_REQ, - INIT_XFR_RECV_PAD, - INIT_XFR_RECV_BYTE_ACK, - INIT_XFR_RECV_BYTE_NACK, - INIT_XFR_FUNCTION_COMPLETE, - INIT_XFR_BUS_COMPLETE, - INIT_XFR_WAIT_REQ, - INIT_CPT_RECV_BYTE_ACK, - INIT_CPT_RECV_WAIT_REQ, - INIT_CPT_RECV_BYTE_NACK - }; - - enum { - // Arbitration - ARB_WAIT_BUS_FREE = 1, - ARB_COMPLETE, - ARB_ASSERT_SEL, - ARB_SET_DEST, - ARB_RELEASE_BUSY, - ARB_TIMEOUT_BUSY, - ARB_TIMEOUT_ABORT, - ARB_DESKEW_WAIT, - - // Send/receive byte - SEND_WAIT_SETTLE, - SEND_WAIT_REQ_0, - RECV_WAIT_REQ_1, - RECV_WAIT_SETTLE, - RECV_WAIT_REQ_0 - }; - - enum { - STATE_MASK = 0x00ff, - SUB_SHIFT = 8, - SUB_MASK = 0xff00 - }; - - enum { BUS_BUSY, BUS_FREE_WAIT, BUS_FREE }; - - enum { - S_GROSS_ERROR = 0x40, - S_PARITY = 0x20, - S_TC0 = 0x10, - S_TCC = 0x08, - - I_SCSI_RESET = 0x80, - I_ILLEGAL = 0x40, - I_DISCONNECT = 0x20, - I_BUS = 0x10, - I_FUNCTION = 0x08, - I_RESELECTED = 0x04, - I_SELECT_ATN = 0x02, - I_SELECTED = 0x01, - - CM_NOP = 0x00, - CM_FLUSH_FIFO = 0x01, - CM_RESET = 0x02, - CM_RESET_BUS = 0x03, - CD_RESELECT = 0x40, - CD_SELECT = 0x41, - CD_SELECT_ATN = 0x42, - CD_SELECT_ATN_STOP = 0x43, - CD_ENABLE_SEL = 0x44, - CD_DISABLE_SEL = 0x45, - CD_SELECT_ATN3 = 0x46, // 53c90a - CT_SEND_MSG = 0x20, - CT_SEND_STATUS = 0x21, - CT_SEND_DATA = 0x22, - CT_DISCONNECT_SEQ = 0x23, - CT_TERMINATE = 0x24, - CT_COMPLETE = 0x25, - CT_DISCONNECT = 0x27, - CT_RECV_MSG = 0x28, - CT_RECV_CMD = 0x29, - CT_RECV_DATA = 0x2a, - CT_RECV_CMD_SEQ = 0x2b, - CT_ABORT_DMA = 0x04, // 53c90a - CI_XFER = 0x10, - CI_COMPLETE = 0x11, - CI_MSG_ACCEPT = 0x12, - CI_PAD = 0x18, - CI_SET_ATN = 0x1a, - CI_RESET_ATN = 0x1b, // 53c90a - }; - - enum { DMA_NONE, DMA_IN, DMA_OUT }; - - emu_timer *tm; - - uint8_t command[2], config, status, istatus; - uint8_t clock_conv, sync_offset, sync_period, bus_id, select_timeout, seq; - uint8_t fifo[16]; - uint16_t tcount; - uint16_t tcounter; - int mode, fifo_pos, command_pos; - int state, xfr_phase; - int command_length; - - int dma_dir; - - bool irq, drq; - bool dma_command; - bool test_mode; - - void dma_set(int dir); - virtual void check_drq(); - - void start_command(); - void step(bool timeout); - virtual bool check_valid_command(uint8_t cmd); - void function_complete(); - void function_bus_complete(); - void bus_complete(); - - void arbitrate(); - void command_pop_and_chain(); - void check_irq(); - - void reset_disconnect(); - - uint8_t fifo_pop(); - void fifo_push(uint8_t val); - void send_byte(); - void recv_byte(); - - void delay(int cycles); - void delay_cycles(int cycles); - - void decrement_tcounter(int count = 1); - - devcb_write_line m_irq_handler; - devcb_write_line m_drq_handler; -}; - -class ncr53c90a_device : public ncr5390_device -{ -public: - ncr53c90a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - virtual void map(address_map &map) override; - - virtual uint8_t status_r() override; - - uint8_t conf2_r() { return config2; } - void conf2_w(uint8_t data) { config2 = data; } - - virtual uint8_t read(offs_t offset) override; - virtual void write(offs_t offset, uint8_t data) override; - -protected: - ncr53c90a_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); - - virtual void device_start() override; - virtual void device_reset() override; - - virtual bool check_valid_command(uint8_t cmd) override; - - // 53c90a uses a previously reserved bit as an interrupt flag - enum { - S_INTERRUPT = 0x80, - }; - - enum conf2_mask : u8 - { - PGDP = 0x01, // pass through/generate data parity - PGRP = 0x02, // pass through/generate register parity - ACDPE = 0x04, // abort on command/data parity error - S2FE = 0x08, // scsi-2 features enable - TSDR = 0x10, // tri-state dma request - SBO = 0x20, // select byte order - LSP = 0x40, // latch scsi phase - DAE = 0x80, // data alignment enable - }; - -private: - u8 config2; -}; - -class ncr53c94_device : public ncr53c90a_device -{ -public: - ncr53c94_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - enum busmd_t : u8 - { - BUSMD_0 = 0, // single bus: 8-bit host, 8 bit dma - BUSMD_1 = 1, // single bus: 8 bit host, 16 bit dma - BUSMD_2 = 2, // two buses: 8 bit multiplexed host, 16 bit dma - BUSMD_3 = 3, // two buses: 8 bit host, 16 bit dma - }; - void set_busmd(busmd_t const busmd) { m_busmd = busmd; } - - virtual void map(address_map &map) override; - - uint8_t conf3_r() { return config3; } - void conf3_w(uint8_t data) { config3 = data; } - void fifo_align_w(uint8_t data) { fifo_align = data; } - - virtual uint8_t read(offs_t offset) override; - virtual void write(offs_t offset, uint8_t data) override; - - u16 dma16_r(); - void dma16_w(u16 data); - -protected: - ncr53c94_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); - - enum conf3_mask : u8 - { - BS8 = 0x01, // burst size 8 - MDM = 0x02, // modify dma mode - LBTM = 0x04, // last byte transfer mode - }; - - virtual void device_start() override; - virtual void device_reset() override; - virtual void check_drq() override; - -private: - u8 config3; - u8 fifo_align; - busmd_t m_busmd; -}; - -class ncr53cf94_device : public ncr53c94_device -{ -public: - ncr53cf94_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); -}; - -DECLARE_DEVICE_TYPE(NCR5390, ncr5390_device) -DECLARE_DEVICE_TYPE(NCR53C90A, ncr53c90a_device) -DECLARE_DEVICE_TYPE(NCR53C94, ncr53c94_device) -DECLARE_DEVICE_TYPE(NCR53CF94, ncr53cf94_device) - -#endif // MAME_MACHINE_NCR5390_H diff --git a/src/devices/machine/ncr53c90.cpp b/src/devices/machine/ncr53c90.cpp new file mode 100644 index 00000000000..5c3e79fb65d --- /dev/null +++ b/src/devices/machine/ncr53c90.cpp @@ -0,0 +1,1288 @@ +// license:BSD-3-Clause +// copyright-holders:Olivier Galibert + +/* + * TODO + * - 16 bit dma order, alignment and last byte handling + * - clean up variable naming and protection + */ + +#include "emu.h" +#include "ncr53c90.h" + +#define LOG_GENERAL (1U << 0) +#define LOG_STATE (1U << 1) +#define LOG_FIFO (1U << 2) +#define LOG_COMMAND (1U << 3) + +#define VERBOSE (0) +#include "logmacro.h" + +#define DELAY_HACK + +DEFINE_DEVICE_TYPE(NCR53C90, ncr53c90_device, "ncr53c90", "NCR 53C90 SCSI Controller") +DEFINE_DEVICE_TYPE(NCR53C90A, ncr53c90a_device, "ncr53c90a", "NCR 53C90A Advanced SCSI Controller") +DEFINE_DEVICE_TYPE(NCR53C94, ncr53c94_device, "ncr53c94", "NCR 53C94 Advanced SCSI Controller") +DEFINE_DEVICE_TYPE(NCR53CF94, ncr53cf94_device, "ncr53cf94", "NCR 53CF94-2 Fast SCSI Controller") // TODO: differences not emulated + +void ncr53c90_device::map(address_map &map) +{ + map(0x0, 0x0).rw(FUNC(ncr53c90_device::tcounter_lo_r), FUNC(ncr53c90_device::tcount_lo_w)); + map(0x1, 0x1).rw(FUNC(ncr53c90_device::tcounter_hi_r), FUNC(ncr53c90_device::tcount_hi_w)); + map(0x2, 0x2).rw(FUNC(ncr53c90_device::fifo_r), FUNC(ncr53c90_device::fifo_w)); + map(0x3, 0x3).rw(FUNC(ncr53c90_device::command_r), FUNC(ncr53c90_device::command_w)); + map(0x4, 0x4).rw(FUNC(ncr53c90_device::status_r), FUNC(ncr53c90_device::bus_id_w)); + map(0x5, 0x5).rw(FUNC(ncr53c90_device::istatus_r), FUNC(ncr53c90_device::timeout_w)); + map(0x6, 0x6).rw(FUNC(ncr53c90_device::seq_step_r), FUNC(ncr53c90_device::sync_period_w)); + map(0x7, 0x7).rw(FUNC(ncr53c90_device::fifo_flags_r), FUNC(ncr53c90_device::sync_offset_w)); + map(0x8, 0x8).rw(FUNC(ncr53c90_device::conf_r), FUNC(ncr53c90_device::conf_w)); + map(0xa, 0xa).w(FUNC(ncr53c90_device::test_w)); + map(0x9, 0x9).w(FUNC(ncr53c90_device::clock_w)); +} + +uint8_t ncr53c90_device::read(offs_t offset) +{ + switch (offset) + { + case 0: return tcounter_lo_r(); + case 1: return tcounter_hi_r(); + case 2: return fifo_r(); + case 3: return command_r(); + case 4: return status_r(); + case 5: return istatus_r(); + case 6: return seq_step_r(); + case 7: return fifo_flags_r(); + case 8: return conf_r(); + default: return 0xff; + } +} + +void ncr53c90_device::write(offs_t offset, uint8_t data) +{ + switch (offset) + { + case 0: tcount_lo_w(data); break; + case 1: tcount_hi_w(data); break; + case 2: fifo_w(data); break; + case 3: command_w(data); break; + case 4: bus_id_w(data); break; + case 5: timeout_w(data); break; + case 6: sync_period_w(data); break; + case 7: sync_offset_w(data); break; + case 8: conf_w(data); break; + case 9: clock_w(data); break; + case 10: test_w(data); break; + default: break; + } +} + +void ncr53c90a_device::map(address_map &map) +{ + ncr53c90_device::map(map); + + map(0xb, 0xb).rw(FUNC(ncr53c90a_device::conf2_r), FUNC(ncr53c90a_device::conf2_w)); +} + +uint8_t ncr53c90a_device::read(offs_t offset) +{ + if (offset == 11) + return conf2_r(); + return ncr53c90_device::read(offset); +} + +void ncr53c90a_device::write(offs_t offset, uint8_t data) +{ + if (offset == 11) + return conf2_w(data); + ncr53c90_device::write(offset, data); +} + +void ncr53c94_device::map(address_map &map) +{ + ncr53c90a_device::map(map); + + map(0xc, 0xc).rw(FUNC(ncr53c94_device::conf3_r), FUNC(ncr53c94_device::conf3_w)); + map(0xf, 0xf).w(FUNC(ncr53c94_device::fifo_align_w)); +} + +uint8_t ncr53c94_device::read(offs_t offset) +{ + if (offset == 12) + return conf3_r(); + return ncr53c90a_device::read(offset); +} + +void ncr53c94_device::write(offs_t offset, uint8_t data) +{ + if (offset == 11) + conf3_w(data); + else if (offset == 15) + fifo_align_w(data); + else + ncr53c90a_device::write(offset, data); +} + +ncr53c90_device::ncr53c90_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) + : nscsi_device(mconfig, type, tag, owner, clock) + , nscsi_slot_card_interface(mconfig, *this, DEVICE_SELF) + , tm(nullptr), config(0), status(0), istatus(0), clock_conv(0), sync_offset(0), sync_period(0), bus_id(0) + , select_timeout(0), seq(0), tcount(0), tcounter(0), mode(0), fifo_pos(0), command_pos(0), state(0), xfr_phase(0), command_length(0), dma_dir(0), irq(false), drq(false), test_mode(false) + , m_irq_handler(*this) + , m_drq_handler(*this) +{ +} + +ncr53c90a_device::ncr53c90a_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) + : ncr53c90_device(mconfig, type, tag, owner, clock) + , config2(0) +{ +} + +ncr53c90_device::ncr53c90_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : ncr53c90_device(mconfig, NCR53C90, tag, owner, clock) +{ +} + +ncr53c90a_device::ncr53c90a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : ncr53c90a_device(mconfig, NCR53C90A, tag, owner, clock) +{ +} + +ncr53c94_device::ncr53c94_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : ncr53c94_device(mconfig, NCR53C94, tag, owner, clock) +{ +} + +ncr53c94_device::ncr53c94_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) + : ncr53c90a_device(mconfig, type, tag, owner, clock) + , config3(0) + , m_busmd(BUSMD_0) +{ +} + +ncr53cf94_device::ncr53cf94_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : ncr53c94_device(mconfig, NCR53CF94, tag, owner, clock) +{ +} + +void ncr53c90_device::device_start() +{ + nscsi_device::device_start(); + + save_item(NAME(command)); + save_item(NAME(config)); + save_item(NAME(status)); + save_item(NAME(istatus)); + save_item(NAME(clock_conv)); + save_item(NAME(sync_offset)); + save_item(NAME(sync_period)); + save_item(NAME(bus_id)); + save_item(NAME(select_timeout)); + save_item(NAME(seq)); + save_item(NAME(fifo)); + save_item(NAME(tcount)); + save_item(NAME(tcounter)); + save_item(NAME(mode)); + save_item(NAME(fifo_pos)); + save_item(NAME(command_pos)); + save_item(NAME(state)); + save_item(NAME(xfr_phase)); + save_item(NAME(command_length)); + save_item(NAME(dma_dir)); + save_item(NAME(irq)); + save_item(NAME(drq)); + save_item(NAME(test_mode)); + + m_irq_handler.resolve_safe(); + m_drq_handler.resolve_safe(); + + config = 0; + bus_id = 0; + select_timeout = 0; + tm = timer_alloc(FUNC(ncr53c90_device::update_tick), this); +} + +void ncr53c90_device::device_reset() +{ + fifo_pos = 0; + memset(fifo, 0, sizeof(fifo)); + + clock_conv = 2; + sync_period = 5; + sync_offset = 0; + seq = 0; + config &= 7; + status = 0; + istatus = 0; + irq = false; + m_irq_handler(irq); + + state = IDLE; + scsi_bus->ctrl_wait(scsi_refid, S_SEL|S_BSY|S_RST, S_ALL); + drq = false; + test_mode = false; + m_drq_handler(drq); + + scsi_bus->ctrl_w(scsi_refid, 0, S_RST); + tcount = 0; + tcounter = 0; + + reset_disconnect(); +} + +void ncr53c90_device::reset_disconnect() +{ + scsi_bus->ctrl_w(scsi_refid, 0, ~S_RST); + + command_pos = 0; + command_length = 0; + memset(command, 0, sizeof(command)); + mode = MODE_D; +} + +void ncr53c90_device::scsi_ctrl_changed() +{ + uint32_t ctrl = scsi_bus->ctrl_r(); + if(ctrl & S_RST) { + LOG("scsi bus reset\n"); + return; + } + + step(false); +} + +TIMER_CALLBACK_MEMBER(ncr53c90_device::update_tick) +{ + step(true); +} + +void ncr53c90_device::step(bool timeout) +{ + uint32_t ctrl = scsi_bus->ctrl_r(); + uint32_t data = scsi_bus->data_r(); + uint8_t c = command[0] & 0x7f; + + LOGMASKED(LOG_STATE, "state=%d.%d %s\n", + state & STATE_MASK, (state & SUB_MASK) >> SUB_SHIFT, + timeout ? "timeout" : "change"); + + if(mode == MODE_I && !(ctrl & S_BSY)) { + state = IDLE; + istatus |= I_DISCONNECT; + reset_disconnect(); + check_irq(); + } + switch(state & SUB_MASK ? state & SUB_MASK : state & STATE_MASK) { + case IDLE: + break; + + case BUSRESET_WAIT_INT: + state = IDLE; + scsi_bus->ctrl_w(scsi_refid, 0, S_RST); + reset_disconnect(); + + if (!(config & 0x40)) { + istatus |= I_SCSI_RESET; + check_irq(); + } + break; + + case ARB_COMPLETE << SUB_SHIFT: { + if(!timeout) + break; + + int win; + for(win=7; win>=0 && !(data & (1<data_w(scsi_refid, 0); + scsi_bus->ctrl_w(scsi_refid, 0, S_ALL); + fatalerror("ncr53c90_device::step need to wait for bus free\n"); + } + state = (state & STATE_MASK) | (ARB_ASSERT_SEL << SUB_SHIFT); + scsi_bus->ctrl_w(scsi_refid, S_SEL, S_SEL); + delay(6); + break; + } + + case ARB_ASSERT_SEL << SUB_SHIFT: + if(!timeout) + break; + + scsi_bus->data_w(scsi_refid, (1<ctrl_w(scsi_refid, c == CD_SELECT_ATN || c == CD_SELECT_ATN_STOP ? S_ATN : 0, S_ATN|S_BSY); + delay(2); + break; + + case ARB_RELEASE_BUSY << SUB_SHIFT: + if(!timeout) + break; + + if(ctrl & S_BSY) { + state = (state & STATE_MASK) | (ARB_DESKEW_WAIT << SUB_SHIFT); + if(c == CD_RESELECT) + scsi_bus->ctrl_w(scsi_refid, S_BSY, S_BSY); + delay_cycles(2); + } else { + state = (state & STATE_MASK) | (ARB_TIMEOUT_BUSY << SUB_SHIFT); +#ifdef DELAY_HACK + delay(1); +#else + delay(8192*select_timeout); +#endif + } + break; + + case ARB_DESKEW_WAIT << SUB_SHIFT: + if(!timeout) + break; + + scsi_bus->data_w(scsi_refid, 0); + scsi_bus->ctrl_w(scsi_refid, 0, S_SEL); + + if(c == CD_RESELECT) { + LOG("mode switch to Target\n"); + mode = MODE_T; + } else { + LOG("mode switch to Initiator\n"); + mode = MODE_I; + } + state &= STATE_MASK; + step(true); + break; + + case ARB_TIMEOUT_BUSY << SUB_SHIFT: + if(timeout) { + scsi_bus->data_w(scsi_refid, 0); + LOG("select timeout\n"); + state = (state & STATE_MASK) | (ARB_TIMEOUT_ABORT << SUB_SHIFT); + delay(1000); + } else if(ctrl & S_BSY) { + state = (state & STATE_MASK) | (ARB_DESKEW_WAIT << SUB_SHIFT); + if(c == CD_RESELECT) + scsi_bus->ctrl_w(scsi_refid, S_BSY, S_BSY); + delay_cycles(2); + } + break; + + case ARB_TIMEOUT_ABORT << SUB_SHIFT: + if(!timeout) + break; + + if(ctrl & S_BSY) { + state = (state & STATE_MASK) | (ARB_DESKEW_WAIT << SUB_SHIFT); + if(c == CD_RESELECT) + scsi_bus->ctrl_w(scsi_refid, S_BSY, S_BSY); + delay_cycles(2); + } else { + scsi_bus->ctrl_w(scsi_refid, 0, S_ALL); + state = IDLE; + istatus |= I_DISCONNECT; + reset_disconnect(); + check_irq(); + } + break; + + case SEND_WAIT_SETTLE << SUB_SHIFT: + if(!timeout) + break; + + state = (state & STATE_MASK) | (SEND_WAIT_REQ_0 << SUB_SHIFT); + step(false); + break; + + case SEND_WAIT_REQ_0 << SUB_SHIFT: + if(ctrl & S_REQ) + break; + state = state & STATE_MASK; + scsi_bus->data_w(scsi_refid, 0); + scsi_bus->ctrl_w(scsi_refid, 0, S_ACK); + step(false); + break; + + case RECV_WAIT_REQ_1 << SUB_SHIFT: + if(!(ctrl & S_REQ)) + break; + + state = (state & STATE_MASK) | (RECV_WAIT_SETTLE << SUB_SHIFT); + delay_cycles(sync_period); + break; + + case RECV_WAIT_SETTLE << SUB_SHIFT: + if(!timeout) + break; + + if((state & STATE_MASK) != INIT_XFR_RECV_PAD) + fifo_push(scsi_bus->data_r()); + scsi_bus->ctrl_w(scsi_refid, S_ACK, S_ACK); + state = (state & STATE_MASK) | (RECV_WAIT_REQ_0 << SUB_SHIFT); + step(false); + break; + + case RECV_WAIT_REQ_0 << SUB_SHIFT: + if(ctrl & S_REQ) + break; + state = state & STATE_MASK; + step(false); + break; + + case DISC_SEL_ARBITRATION_INIT: + // wait until a command is in the fifo + if (!fifo_pos) { + // dma starts after bus arbitration/selection is complete + check_drq(); + break; + } + + command_length = fifo_pos + tcounter; + state = DISC_SEL_ARBITRATION; + step(false); + break; + + case DISC_SEL_ARBITRATION: + if(c == CD_SELECT) { + state = DISC_SEL_WAIT_REQ; + } else + state = DISC_SEL_ATN_WAIT_REQ; + + scsi_bus->ctrl_wait(scsi_refid, S_REQ, S_REQ); + if(ctrl & S_REQ) + step(false); + break; + + case DISC_SEL_ATN_WAIT_REQ: + if(!(ctrl & S_REQ)) + break; + if((ctrl & S_PHASE_MASK) != S_PHASE_MSG_OUT) { + function_complete(); + break; + } + if(c == CD_SELECT_ATN || c == CD_SELECT_ATN_STOP) + scsi_bus->ctrl_w(scsi_refid, 0, S_ATN); + state = DISC_SEL_ATN_SEND_BYTE; + send_byte(); + break; + + case DISC_SEL_ATN_SEND_BYTE: + command_length--; + if(c == CD_SELECT_ATN_STOP) { + seq = 2; + function_bus_complete(); + } else { + state = DISC_SEL_WAIT_REQ; + } + break; + + case DISC_SEL_WAIT_REQ: + if(!(ctrl & S_REQ)) + break; + if((ctrl & S_PHASE_MASK) != S_PHASE_COMMAND) { + if(!command_length) + seq = 4; + else + seq = 2; + scsi_bus->ctrl_wait(scsi_refid, 0, S_REQ); + function_bus_complete(); + break; + } + if(seq < 3) + seq = 3; + state = DISC_SEL_SEND_BYTE; + send_byte(); + break; + + case DISC_SEL_SEND_BYTE: + if(command_length) { + command_length--; + if(!command_length) + seq = 4; + } + + state = DISC_SEL_WAIT_REQ; + break; + + case INIT_CPT_RECV_BYTE_ACK: + state = INIT_CPT_RECV_WAIT_REQ; + scsi_bus->ctrl_w(scsi_refid, 0, S_ACK); + break; + + case INIT_CPT_RECV_WAIT_REQ: + if(!(ctrl & S_REQ)) + break; + + if((ctrl & S_PHASE_MASK) != S_PHASE_MSG_IN) { + command_pos = 0; + bus_complete(); + } else { + state = INIT_CPT_RECV_BYTE_NACK; + recv_byte(); + } + break; + + case INIT_CPT_RECV_BYTE_NACK: + function_complete(); + break; + + case INIT_MSG_WAIT_REQ: + if((ctrl & (S_REQ|S_BSY)) == S_BSY) + break; + bus_complete(); + break; + + case INIT_XFR: + switch(xfr_phase) { + case S_PHASE_DATA_OUT: + case S_PHASE_COMMAND: + case S_PHASE_MSG_OUT: + state = INIT_XFR_SEND_BYTE; + + // can't send if the fifo is empty + if (fifo_pos == 0) + break; + + // if it's the last message byte, deassert ATN before sending + if (xfr_phase == S_PHASE_MSG_OUT && ((!dma_command && fifo_pos == 1) || (dma_command && tcounter == 1))) + scsi_bus->ctrl_w(scsi_refid, 0, S_ATN); + + send_byte(); + break; + + case S_PHASE_DATA_IN: + case S_PHASE_STATUS: + case S_PHASE_MSG_IN: + // can't receive if the fifo is full + if (fifo_pos == 16) + break; + + // if it's the last message byte, ACK remains asserted, terminate with function_complete() + state = (xfr_phase == S_PHASE_MSG_IN && (!dma_command || tcounter == 1)) ? INIT_XFR_RECV_BYTE_NACK : INIT_XFR_RECV_BYTE_ACK; + + recv_byte(); + break; + + default: + LOG("xfer on phase %d\n", scsi_bus->ctrl_r() & S_PHASE_MASK); + function_complete(); + break; + } + break; + + case INIT_XFR_WAIT_REQ: + if(!(ctrl & S_REQ)) + break; + + // check for command complete + if ((dma_command && (status & S_TC0) && (dma_dir == DMA_IN || fifo_pos == 0)) // dma in/out: transfer count == 0 + || (!dma_command && (xfr_phase & S_INP) == 0 && fifo_pos == 0) // non-dma out: fifo empty + || (!dma_command && (xfr_phase & S_INP) == S_INP && fifo_pos == 1)) // non-dma in: every byte + state = INIT_XFR_BUS_COMPLETE; + else + // check for phase change + if((ctrl & S_PHASE_MASK) != xfr_phase) { + command_pos = 0; + state = INIT_XFR_BUS_COMPLETE; + } else { + state = INIT_XFR; + } + step(false); + break; + + case INIT_XFR_SEND_BYTE: + state = INIT_XFR_WAIT_REQ; + step(false); + break; + + case INIT_XFR_RECV_BYTE_ACK: + state = INIT_XFR_WAIT_REQ; + scsi_bus->ctrl_w(scsi_refid, 0, S_ACK); + break; + + case INIT_XFR_RECV_BYTE_NACK: + state = INIT_XFR_FUNCTION_COMPLETE; + step(false); + break; + + case INIT_XFR_FUNCTION_COMPLETE: + // wait for dma transfer to complete or fifo to drain + if (dma_command && !(status & S_TC0) && fifo_pos) + break; + + function_complete(); + break; + + case INIT_XFR_BUS_COMPLETE: + // wait for dma transfer to complete or fifo to drain + if (dma_command && !(status & S_TC0) && fifo_pos) + break; + bus_complete(); + break; + + case INIT_XFR_SEND_PAD_WAIT_REQ: + if(!(ctrl & S_REQ)) + break; + + if((ctrl & S_PHASE_MASK) != xfr_phase) { + command_pos = 0; + bus_complete(); + } else { + state = INIT_XFR_SEND_PAD; + send_byte(); + } + break; + + case INIT_XFR_SEND_PAD: + decrement_tcounter(); + if(!(status & S_TC0)) { + state = INIT_XFR_SEND_PAD_WAIT_REQ; + step(false); + } else + function_complete(); + break; + + case INIT_XFR_RECV_PAD_WAIT_REQ: + if(!(ctrl & S_REQ)) + break; + + if((ctrl & S_PHASE_MASK) != xfr_phase) { + command_pos = 0; + bus_complete(); + } else { + state = INIT_XFR_RECV_PAD; + recv_byte(); + } + break; + + case INIT_XFR_RECV_PAD: + decrement_tcounter(); + if(!(status & S_TC0)) { + state = INIT_XFR_RECV_PAD_WAIT_REQ; + scsi_bus->ctrl_w(scsi_refid, 0, S_ACK); + step(false); + } else + function_complete(); + break; + + default: + LOG("step() unexpected state %d.%d\n", + state & STATE_MASK, (state & SUB_MASK) >> SUB_SHIFT); + exit(0); + } +} + +void ncr53c90_device::send_byte() +{ + if(!fifo_pos) + fatalerror("ncr53c90_device::send_byte - !fifo_pos\n"); + + state = (state & STATE_MASK) | (SEND_WAIT_SETTLE << SUB_SHIFT); + if((state & STATE_MASK) != INIT_XFR_SEND_PAD && + ((state & STATE_MASK) != DISC_SEL_SEND_BYTE || + command_length)) + scsi_bus->data_w(scsi_refid, fifo_pop()); + else + scsi_bus->data_w(scsi_refid, 0); + + scsi_bus->ctrl_w(scsi_refid, S_ACK, S_ACK); + scsi_bus->ctrl_wait(scsi_refid, S_REQ, S_REQ); + delay_cycles(sync_period); +} + +void ncr53c90_device::recv_byte() +{ + scsi_bus->ctrl_wait(scsi_refid, S_REQ, S_REQ); + state = (state & STATE_MASK) | (RECV_WAIT_REQ_1 << SUB_SHIFT); + step(false); +} + +void ncr53c90_device::function_bus_complete() +{ + LOG("function_bus_complete\n"); + state = IDLE; + istatus |= I_FUNCTION|I_BUS; + dma_set(DMA_NONE); + check_drq(); + check_irq(); +} + +void ncr53c90_device::function_complete() +{ + LOG("function_complete\n"); + state = IDLE; + istatus |= I_FUNCTION; + dma_set(DMA_NONE); + check_drq(); + check_irq(); +} + +void ncr53c90_device::bus_complete() +{ + LOG("bus_complete\n"); + state = IDLE; + istatus |= I_BUS; + dma_set(DMA_NONE); + check_drq(); + check_irq(); +} + +void ncr53c90_device::delay(int cycles) +{ + if(!clock_conv) + return; + cycles *= clock_conv; + tm->adjust(clocks_to_attotime(cycles)); +} + +void ncr53c90_device::delay_cycles(int cycles) +{ + tm->adjust(clocks_to_attotime(cycles)); +} + +uint8_t ncr53c90_device::tcounter_lo_r() +{ + LOG("tcounter_lo_r %02x (%s)\n", tcounter & 0xff, machine().describe_context()); + return tcounter; +} + +void ncr53c90_device::tcount_lo_w(uint8_t data) +{ + tcount = (tcount & 0xff00) | data; + LOG("tcount_lo_w %02x (%s)\n", data, machine().describe_context()); +} + +uint8_t ncr53c90_device::tcounter_hi_r() +{ + LOG("tcounter_hi_r %02x (%s)\n", tcounter >> 8, machine().describe_context()); + return tcounter >> 8; +} + +void ncr53c90_device::tcount_hi_w(uint8_t data) +{ + tcount = (tcount & 0x00ff) | (data << 8); + LOG("tcount_hi_w %02x (%s)\n", data, machine().describe_context()); +} + +uint8_t ncr53c90_device::fifo_pop() +{ + uint8_t r = fifo[0]; + fifo_pos--; + memmove(fifo, fifo+1, fifo_pos); + check_drq(); + return r; +} + +void ncr53c90_device::fifo_push(uint8_t val) +{ + fifo[fifo_pos++] = val; + check_drq(); +} + +uint8_t ncr53c90_device::fifo_r() +{ + uint8_t r; + if(fifo_pos) { + r = fifo[0]; + fifo_pos--; + memmove(fifo, fifo+1, fifo_pos); + } else + r = 0; + LOGMASKED(LOG_FIFO, "fifo_r 0x%02x fifo_pos %d (%s)\n", r, fifo_pos, machine().describe_context()); + return r; +} + +void ncr53c90_device::fifo_w(uint8_t data) +{ + LOGMASKED(LOG_FIFO, "fifo_w 0x%02x fifo_pos %d (%s)\n", data, fifo_pos, machine().describe_context()); + if(fifo_pos != 16) + fifo[fifo_pos++] = data; +} + +uint8_t ncr53c90_device::command_r() +{ + LOG("command_r (%s)\n", machine().describe_context()); + return command[0]; +} + +void ncr53c90_device::command_w(uint8_t data) +{ + LOG("command_w %02x command_pos %d (%s)\n", data, command_pos, machine().describe_context()); + if(command_pos == 2) { + status |= S_GROSS_ERROR; + check_irq(); + return; + } + /* + * Note the RESET chip and RESET SCSI Bus commands execute as soon as they are loaded into + * the top of the Command Register. + */ + if((data & 0x7f) == CM_RESET || (data & 0x7f) == CM_RESET_BUS) + command_pos = 0; + + command[command_pos++] = data; + if(command_pos == 1) + start_command(); +} + +void ncr53c90_device::command_pop_and_chain() +{ + if(command_pos) { + command_pos--; + if(command_pos) { + command[0] = command[1]; + start_command(); + } + } +} + +void ncr53c90_device::start_command() +{ + uint8_t c = command[0] & 0x7f; + if(!check_valid_command(c)) { + LOG("invalid command %02x\n", command[0]); + istatus |= I_ILLEGAL; + check_irq(); + return; + } + + // for dma commands, reload transfer counter + dma_command = command[0] & 0x80; + if (dma_command) + { + tcounter = tcount; + + // clear transfer count zero flag when counter is reloaded + status &= ~S_TC0; + } + else + tcounter = 0; + + switch(c) { + case CM_NOP: + LOGMASKED(LOG_COMMAND, "NOP\n"); + command_pop_and_chain(); + break; + + case CM_FLUSH_FIFO: + LOGMASKED(LOG_COMMAND, "Flush FIFO\n"); + fifo_pos = 0; + command_pop_and_chain(); + break; + + case CM_RESET: + LOGMASKED(LOG_COMMAND, "Reset chip\n"); + device_reset(); + break; + + case CM_RESET_BUS: + LOGMASKED(LOG_COMMAND, "Reset SCSI bus\n"); + state = BUSRESET_WAIT_INT; + scsi_bus->ctrl_w(scsi_refid, S_RST, S_RST); + delay(130); + break; + + case CD_RESELECT: + LOGMASKED(LOG_COMMAND, "Reselect sequence\n"); + state = DISC_REC_ARBITRATION; + arbitrate(); + break; + + case CD_SELECT: + case CD_SELECT_ATN: + case CD_SELECT_ATN_STOP: + LOGMASKED(LOG_COMMAND, + (c == CD_SELECT) ? "Select without ATN sequence\n" : + (c == CD_SELECT_ATN) ? "Select with ATN sequence\n" : + "Select with ATN and stop sequence\n"); + seq = 0; + state = DISC_SEL_ARBITRATION_INIT; + dma_set(dma_command ? DMA_OUT : DMA_NONE); + arbitrate(); + break; + + case CD_ENABLE_SEL: + LOGMASKED(LOG_COMMAND, "Enable selection/reselection\n"); + command_pop_and_chain(); + break; + + case CD_DISABLE_SEL: + LOGMASKED(LOG_COMMAND, "Disable selection/reselection\n"); + command_pop_and_chain(); + break; + + case CI_XFER: + LOGMASKED(LOG_COMMAND, "Transfer information\n"); + state = INIT_XFR; + xfr_phase = scsi_bus->ctrl_r() & S_PHASE_MASK; + dma_set(dma_command ? ((xfr_phase & S_INP) ? DMA_IN : DMA_OUT) : DMA_NONE); + check_drq(); + step(false); + break; + + case CI_COMPLETE: + LOGMASKED(LOG_COMMAND, "Initiator command complete sequence\n"); + state = INIT_CPT_RECV_BYTE_ACK; + dma_set(dma_command ? DMA_IN : DMA_NONE); + recv_byte(); + break; + + case CI_MSG_ACCEPT: + LOGMASKED(LOG_COMMAND, "Message accepted\n"); + state = INIT_MSG_WAIT_REQ; + // It's undocumented what the sequence register should contain after a message accept + // command, but the InterPro boot code expects it to be non-zero; setting it to an + // arbirary 1 here makes InterPro happy. Also in the InterPro case (perhaps typical), + // after ACK is asserted the device disconnects and the INIT_MSG_WAIT_REQ state is never + // entered, meaning we end up with I_DISCONNECT instead of I_BUS interrupt status. + seq = 2; + scsi_bus->ctrl_w(scsi_refid, 0, S_ACK); + step(false); + break; + + case CI_PAD: + LOGMASKED(LOG_COMMAND, "Transfer pad\n"); + xfr_phase = scsi_bus->ctrl_r() & S_PHASE_MASK; + if(xfr_phase & S_INP) + state = INIT_XFR_RECV_PAD_WAIT_REQ; + else + state = INIT_XFR_SEND_PAD_WAIT_REQ; + scsi_bus->ctrl_w(scsi_refid, 0, S_ACK); + step(false); + break; + + case CI_SET_ATN: + LOGMASKED(LOG_COMMAND, "Set ATN\n"); + scsi_bus->ctrl_w(scsi_refid, S_ATN, S_ATN); + command_pop_and_chain(); + break; + + case CI_RESET_ATN: + LOGMASKED(LOG_COMMAND, "Reset ATN\n"); + scsi_bus->ctrl_w(scsi_refid, 0, S_ATN); + command_pop_and_chain(); + break; + + default: + fatalerror("ncr53c90_device::start_command unimplemented command %02x\n", c); + } +} + +bool ncr53c90_device::check_valid_command(uint8_t cmd) +{ + int subcmd = cmd & 15; + switch((cmd >> 4) & 7) { + case 0: return subcmd <= 3; + case 4: return mode == MODE_D && subcmd <= 5; + case 2: return mode == MODE_T && subcmd <= 11 && subcmd != 6; + case 1: return mode == MODE_I && (subcmd <= 2 || subcmd == 8 || subcmd == 10); + } + return false; +} + +void ncr53c90_device::arbitrate() +{ + state = (state & STATE_MASK) | (ARB_COMPLETE << SUB_SHIFT); + scsi_bus->data_w(scsi_refid, 1 << scsi_id); + scsi_bus->ctrl_w(scsi_refid, S_BSY, S_BSY); + delay(11); +} + +void ncr53c90_device::check_irq() +{ + bool oldirq = irq; + irq = istatus != 0; + if(irq != oldirq) + m_irq_handler(irq); + +} + +uint8_t ncr53c90_device::status_r() +{ + uint32_t ctrl = scsi_bus->ctrl_r(); + uint8_t res = status | (ctrl & S_MSG ? 4 : 0) | (ctrl & S_CTL ? 2 : 0) | (ctrl & S_INP ? 1 : 0); + LOG("status_r %02x (%s)\n", res, machine().describe_context()); + + return res; +} + +void ncr53c90_device::bus_id_w(uint8_t data) +{ + bus_id = data & 7; + LOG("bus_id=%d\n", bus_id); +} + +uint8_t ncr53c90_device::istatus_r() +{ + uint8_t res = istatus; + + if (irq) + { + status &= ~(S_GROSS_ERROR | S_PARITY | S_TCC); + istatus = 0; + seq = 0; + } + check_irq(); + if(res) + command_pop_and_chain(); + + LOG("istatus_r %02x (%s)\n", res, machine().describe_context()); + return res; +} + +void ncr53c90_device::timeout_w(uint8_t data) +{ + LOG("timeout_w 0x%02x\n", data); + select_timeout = data; +} + +uint8_t ncr53c90_device::seq_step_r() +{ + LOG("seq_step_r %d (%s)\n", seq, machine().describe_context()); + return seq; +} + +void ncr53c90_device::sync_period_w(uint8_t data) +{ + sync_period = data & 0x1f; +} + +uint8_t ncr53c90_device::fifo_flags_r() +{ + return fifo_pos; +} + +void ncr53c90_device::sync_offset_w(uint8_t data) +{ + sync_offset = data & 0x0f; +} + +uint8_t ncr53c90_device::conf_r() +{ + return config; +} + +void ncr53c90_device::conf_w(uint8_t data) +{ + config = data; + scsi_id = data & 7; + + // test mode can only be cleared by hard/soft reset + if (data & 0x8) + test_mode = true; +} + +void ncr53c90_device::test_w(uint8_t data) +{ + if (test_mode) + logerror("test_w %d (%s) - test mode not implemented\n", data, machine().describe_context()); +} + +void ncr53c90_device::clock_w(uint8_t data) +{ + clock_conv = data & 0x07; +} + +void ncr53c90_device::dma_set(int dir) +{ + dma_dir = dir; + + // account for data already in the fifo + if (dir == DMA_OUT && fifo_pos) + decrement_tcounter(fifo_pos); +} + +void ncr53c90_device::dma_w(uint8_t val) +{ + fifo_push(val); + decrement_tcounter(); + check_drq(); + step(false); +} + +uint8_t ncr53c90_device::dma_r() +{ + uint8_t r = fifo_pop(); + decrement_tcounter(); + check_drq(); + step(false); + return r; +} + +void ncr53c90_device::check_drq() +{ + bool drq_state = drq; + + switch (dma_dir) { + case DMA_NONE: + drq_state = false; + break; + + case DMA_IN: // device to memory + drq_state = !(status & S_TC0) && fifo_pos; + break; + + case DMA_OUT: // memory to device + drq_state = !(status & S_TC0) && fifo_pos < 16; + break; + } + + if (drq_state != drq) { + drq = drq_state; + m_drq_handler(drq); + } +} + +void ncr53c90_device::decrement_tcounter(int count) +{ + if (!dma_command) + return; + + tcounter -= count; + if (tcounter == 0) + status |= S_TC0; +} + +/* + * According to the NCR 53C90A, 53C90B data book (http://bitsavers.org/pdf/ncr/scsi/NCR53C90ab.pdf), + * the following are the differences from the 53C90: + * + * - Supports three-byte message exchange SCSI-2 tagged queueing + * - Added select with ATN3 command + * - Added target DMA abort command + * - Added interrupt polling bit + * - Added second configuration register + * - Improved immunity to cable impedance mismatches and improper termination + * - Tri-state DMA request output + * - Cut leakage current on SCSI input pins when powered off + * - Relaxed register timings + * - Relaxed DMA timings + * - Relaxed CLK duty cycle + * - Lengthened read data access time + * - NOP required less often + */ + +void ncr53c90a_device::device_start() +{ + save_item(NAME(config2)); + + config2 = 0; + + ncr53c90_device::device_start(); +} + +void ncr53c90a_device::device_reset() +{ + config2 = 0; + + ncr53c90_device::device_reset(); +} + +uint8_t ncr53c90a_device::status_r() +{ + uint32_t ctrl = scsi_bus->ctrl_r(); + uint8_t res = (irq ? S_INTERRUPT : 0) | status | (ctrl & S_MSG ? 4 : 0) | (ctrl & S_CTL ? 2 : 0) | (ctrl & S_INP ? 1 : 0); + LOG("status_r %02x (%s)\n", res, machine().describe_context()); + if (irq) + status &= ~(S_GROSS_ERROR | S_PARITY | S_TCC); + return res; +} + +bool ncr53c90a_device::check_valid_command(uint8_t cmd) +{ + int subcmd = cmd & 15; + switch ((cmd >> 4) & 7) { + case 0: return subcmd <= 3 || (mode == MODE_T && subcmd == 4); + case 4: return mode == MODE_D && subcmd <= 6; + case 2: return mode == MODE_T && subcmd <= 11 && subcmd != 6; + case 1: return mode == MODE_I && (subcmd <= 2 || subcmd == 8 || subcmd == 10 || subcmd == 11); + } + return false; +} + +void ncr53c94_device::device_start() +{ + save_item(NAME(config3)); + + config3 = 0; + + ncr53c90a_device::device_start(); +} + +void ncr53c94_device::device_reset() +{ + config3 = 0; + + ncr53c90a_device::device_reset(); +} + +u16 ncr53c94_device::dma16_r() +{ + // check fifo underflow + if (fifo_pos < 2) + fatalerror("ncr53c94_device::dma16_r fifo_pos %d\n", fifo_pos); + + // pop two bytes from fifo + u16 const data = (fifo[0] << 8) | fifo[1]; + fifo_pos -= 2; + memmove(fifo, fifo + 2, fifo_pos); + + // update drq + decrement_tcounter(2); + check_drq(); + + step(false); + + return data; +} + +void ncr53c94_device::dma16_w(u16 data) +{ + // check fifo overflow + if (fifo_pos > 14) + fatalerror("ncr53c94_device::dma16_w fifo_pos %d\n", fifo_pos); + + // push two bytes into fifo + fifo[fifo_pos++] = data >> 8; + fifo[fifo_pos++] = data; + + // update drq + decrement_tcounter(2); + check_drq(); + + step(false); +} + +void ncr53c94_device::check_drq() +{ + if (m_busmd != BUSMD_0) + { + bool drq_state = drq; + + switch (dma_dir) { + case DMA_NONE: + drq_state = false; + break; + + case DMA_IN: // device to memory + drq_state = !(status & S_TC0) && fifo_pos > 1; + break; + + case DMA_OUT: // memory to device + drq_state = !(status & S_TC0) && fifo_pos < 15; + break; + } + + if (drq_state != drq) { + drq = drq_state; + m_drq_handler(drq); + } + } + else + ncr53c90_device::check_drq(); +} diff --git a/src/devices/machine/ncr53c90.h b/src/devices/machine/ncr53c90.h new file mode 100644 index 00000000000..666c9c7a8e4 --- /dev/null +++ b/src/devices/machine/ncr53c90.h @@ -0,0 +1,341 @@ +// license:BSD-3-Clause +// copyright-holders:Olivier Galibert +#ifndef MAME_MACHINE_NCR53C90_H +#define MAME_MACHINE_NCR53C90_H + +#pragma once + +#include "machine/nscsi_bus.h" + +class ncr53c90_device : public nscsi_device, public nscsi_slot_card_interface +{ +public: + ncr53c90_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + // configuration helpers + auto irq_handler_cb() { return m_irq_handler.bind(); } + auto drq_handler_cb() { return m_drq_handler.bind(); } + + virtual void map(address_map &map); + + uint8_t tcounter_lo_r(); + void tcount_lo_w(uint8_t data); + uint8_t tcounter_hi_r(); + void tcount_hi_w(uint8_t data); + uint8_t fifo_r(); + void fifo_w(uint8_t data); + uint8_t command_r(); + void command_w(uint8_t data); + virtual uint8_t status_r(); + void bus_id_w(uint8_t data); + uint8_t istatus_r(); + void timeout_w(uint8_t data); + uint8_t seq_step_r(); + void sync_period_w(uint8_t data); + uint8_t fifo_flags_r(); + void sync_offset_w(uint8_t data); + uint8_t conf_r(); + void conf_w(uint8_t data); + void test_w(uint8_t data); + void clock_w(uint8_t data); + + virtual uint8_t read(offs_t offset); + virtual void write(offs_t offset, uint8_t data); + + virtual void scsi_ctrl_changed() override; + + uint8_t dma_r(); + void dma_w(uint8_t val); + +protected: + ncr53c90_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + + virtual void device_start() override; + virtual void device_reset() override; + + TIMER_CALLBACK_MEMBER(update_tick); + + enum { MODE_D, MODE_T, MODE_I }; + enum { IDLE }; + + enum { + // Bus initiated sequences + BUSINIT_SETTLE_DELAY = 1, + BUSINIT_ASSERT_BUS_SEL, + BUSINIT_MSG_OUT, + BUSINIT_RECV_BYTE, + BUSINIT_ASSERT_BUS_RESEL, + BUSINIT_WAIT_REQ, + BUSINIT_RECV_BYTE_NACK, + + // Bus SCSI Reset + BUSRESET_WAIT_INT, + BUSRESET_RESET_BOARD, + + // Disconnected state commands + DISC_SEL_ARBITRATION_INIT, + DISC_SEL_ARBITRATION, + DISC_SEL_ATN_WAIT_REQ, + DISC_SEL_ATN_SEND_BYTE, + DISC_SEL_WAIT_REQ, + DISC_SEL_SEND_BYTE, + DISC_REC_ARBITRATION, + DISC_REC_MSG_IN, + DISC_REC_SEND_BYTE, + DISC_RESET, + + // Command sequence + CMDSEQ_CMD_PHASE, + CMDSEQ_RECV_BYTE, + + // Target commands + TARGET_SEND_BYTE, + TARGET_CMD_RECV_BYTE, + TARGET_MSG_RECV_BYTE, + TARGET_MSG_RECV_PAD, + TARGET_DISC_SEND_BYTE, + TARGET_DISC_MSG_IN, + TARGET_DISC_SEND_BYTE_2, + + // Initiator commands + INIT_MSG_WAIT_REQ, + INIT_XFR, + INIT_XFR_SEND_BYTE, + INIT_XFR_SEND_PAD_WAIT_REQ, + INIT_XFR_SEND_PAD, + INIT_XFR_RECV_PAD_WAIT_REQ, + INIT_XFR_RECV_PAD, + INIT_XFR_RECV_BYTE_ACK, + INIT_XFR_RECV_BYTE_NACK, + INIT_XFR_FUNCTION_COMPLETE, + INIT_XFR_BUS_COMPLETE, + INIT_XFR_WAIT_REQ, + INIT_CPT_RECV_BYTE_ACK, + INIT_CPT_RECV_WAIT_REQ, + INIT_CPT_RECV_BYTE_NACK + }; + + enum { + // Arbitration + ARB_WAIT_BUS_FREE = 1, + ARB_COMPLETE, + ARB_ASSERT_SEL, + ARB_SET_DEST, + ARB_RELEASE_BUSY, + ARB_TIMEOUT_BUSY, + ARB_TIMEOUT_ABORT, + ARB_DESKEW_WAIT, + + // Send/receive byte + SEND_WAIT_SETTLE, + SEND_WAIT_REQ_0, + RECV_WAIT_REQ_1, + RECV_WAIT_SETTLE, + RECV_WAIT_REQ_0 + }; + + enum { + STATE_MASK = 0x00ff, + SUB_SHIFT = 8, + SUB_MASK = 0xff00 + }; + + enum { BUS_BUSY, BUS_FREE_WAIT, BUS_FREE }; + + enum { + S_GROSS_ERROR = 0x40, + S_PARITY = 0x20, + S_TC0 = 0x10, + S_TCC = 0x08, + + I_SCSI_RESET = 0x80, + I_ILLEGAL = 0x40, + I_DISCONNECT = 0x20, + I_BUS = 0x10, + I_FUNCTION = 0x08, + I_RESELECTED = 0x04, + I_SELECT_ATN = 0x02, + I_SELECTED = 0x01, + + CM_NOP = 0x00, + CM_FLUSH_FIFO = 0x01, + CM_RESET = 0x02, + CM_RESET_BUS = 0x03, + CD_RESELECT = 0x40, + CD_SELECT = 0x41, + CD_SELECT_ATN = 0x42, + CD_SELECT_ATN_STOP = 0x43, + CD_ENABLE_SEL = 0x44, + CD_DISABLE_SEL = 0x45, + CD_SELECT_ATN3 = 0x46, // 53c90a + CT_SEND_MSG = 0x20, + CT_SEND_STATUS = 0x21, + CT_SEND_DATA = 0x22, + CT_DISCONNECT_SEQ = 0x23, + CT_TERMINATE = 0x24, + CT_COMPLETE = 0x25, + CT_DISCONNECT = 0x27, + CT_RECV_MSG = 0x28, + CT_RECV_CMD = 0x29, + CT_RECV_DATA = 0x2a, + CT_RECV_CMD_SEQ = 0x2b, + CT_ABORT_DMA = 0x04, // 53c90a + CI_XFER = 0x10, + CI_COMPLETE = 0x11, + CI_MSG_ACCEPT = 0x12, + CI_PAD = 0x18, + CI_SET_ATN = 0x1a, + CI_RESET_ATN = 0x1b, // 53c90a + }; + + enum { DMA_NONE, DMA_IN, DMA_OUT }; + + emu_timer *tm; + + uint8_t command[2], config, status, istatus; + uint8_t clock_conv, sync_offset, sync_period, bus_id, select_timeout, seq; + uint8_t fifo[16]; + uint16_t tcount; + uint16_t tcounter; + int mode, fifo_pos, command_pos; + int state, xfr_phase; + int command_length; + + int dma_dir; + + bool irq, drq; + bool dma_command; + bool test_mode; + + void dma_set(int dir); + virtual void check_drq(); + + void start_command(); + void step(bool timeout); + virtual bool check_valid_command(uint8_t cmd); + void function_complete(); + void function_bus_complete(); + void bus_complete(); + + void arbitrate(); + void command_pop_and_chain(); + void check_irq(); + + void reset_disconnect(); + + uint8_t fifo_pop(); + void fifo_push(uint8_t val); + void send_byte(); + void recv_byte(); + + void delay(int cycles); + void delay_cycles(int cycles); + + void decrement_tcounter(int count = 1); + + devcb_write_line m_irq_handler; + devcb_write_line m_drq_handler; +}; + +class ncr53c90a_device : public ncr53c90_device +{ +public: + ncr53c90a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + virtual void map(address_map &map) override; + + virtual uint8_t status_r() override; + + uint8_t conf2_r() { return config2; } + void conf2_w(uint8_t data) { config2 = data; } + + virtual uint8_t read(offs_t offset) override; + virtual void write(offs_t offset, uint8_t data) override; + +protected: + ncr53c90a_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + + virtual void device_start() override; + virtual void device_reset() override; + + virtual bool check_valid_command(uint8_t cmd) override; + + // 53c90a uses a previously reserved bit as an interrupt flag + enum { + S_INTERRUPT = 0x80, + }; + + enum conf2_mask : u8 + { + PGDP = 0x01, // pass through/generate data parity + PGRP = 0x02, // pass through/generate register parity + ACDPE = 0x04, // abort on command/data parity error + S2FE = 0x08, // scsi-2 features enable + TSDR = 0x10, // tri-state dma request + SBO = 0x20, // select byte order + LSP = 0x40, // latch scsi phase + DAE = 0x80, // data alignment enable + }; + +private: + u8 config2; +}; + +class ncr53c94_device : public ncr53c90a_device +{ +public: + ncr53c94_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + enum busmd_t : u8 + { + BUSMD_0 = 0, // single bus: 8-bit host, 8 bit dma + BUSMD_1 = 1, // single bus: 8 bit host, 16 bit dma + BUSMD_2 = 2, // two buses: 8 bit multiplexed host, 16 bit dma + BUSMD_3 = 3, // two buses: 8 bit host, 16 bit dma + }; + void set_busmd(busmd_t const busmd) { m_busmd = busmd; } + + virtual void map(address_map &map) override; + + uint8_t conf3_r() { return config3; } + void conf3_w(uint8_t data) { config3 = data; } + void fifo_align_w(uint8_t data) { fifo_align = data; } + + virtual uint8_t read(offs_t offset) override; + virtual void write(offs_t offset, uint8_t data) override; + + u16 dma16_r(); + void dma16_w(u16 data); + +protected: + ncr53c94_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + + enum conf3_mask : u8 + { + BS8 = 0x01, // burst size 8 + MDM = 0x02, // modify dma mode + LBTM = 0x04, // last byte transfer mode + }; + + virtual void device_start() override; + virtual void device_reset() override; + virtual void check_drq() override; + +private: + u8 config3; + u8 fifo_align; + busmd_t m_busmd; +}; + +class ncr53cf94_device : public ncr53c94_device +{ +public: + ncr53cf94_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); +}; + +DECLARE_DEVICE_TYPE(NCR53C90, ncr53c90_device) +DECLARE_DEVICE_TYPE(NCR53C90A, ncr53c90a_device) +DECLARE_DEVICE_TYPE(NCR53C94, ncr53c94_device) +DECLARE_DEVICE_TYPE(NCR53CF94, ncr53cf94_device) + +#endif // MAME_MACHINE_NCR53C90_H diff --git a/src/devices/machine/spifi3.cpp b/src/devices/machine/spifi3.cpp index d7a2b40719c..98acba7b731 100644 --- a/src/devices/machine/spifi3.cpp +++ b/src/devices/machine/spifi3.cpp @@ -7,7 +7,7 @@ * References: * - https://github.com/NetBSD/src/blob/trunk/sys/arch/newsmips/apbus/spifireg.h * - https://github.com/NetBSD/src/blob/trunk/sys/arch/newsmips/apbus/spifi.c - * - https://github.com/mamedev/mame/blob/master/src/devices/machine/ncr5390.cpp + * - https://github.com/mamedev/mame/blob/master/src/devices/machine/ncr53c90.cpp * * TODO: * - NetBSD compatibility diff --git a/src/devices/machine/spifi3.h b/src/devices/machine/spifi3.h index 271250b7dca..6afa51ded06 100644 --- a/src/devices/machine/spifi3.h +++ b/src/devices/machine/spifi3.h @@ -15,12 +15,12 @@ * In its current state, this driver is unlikely to work out of the box with any other machines. * * Register definitions were derived from the NetBSD source code, copyright (c) 2000 Tsubai Masanari. - * SCSI state machine code was derived from the MAME NCR5390 driver, copyright (c) Olivier Galibert + * SCSI state machine code was derived from the MAME NCR53C90 driver, copyright (c) Olivier Galibert * * References: * - https://github.com/NetBSD/src/blob/trunk/sys/arch/newsmips/apbus/spifireg.h * - https://github.com/NetBSD/src/blob/trunk/sys/arch/newsmips/apbus/spifi.c - * - https://github.com/mamedev/mame/blob/master/src/devices/machine/ncr5390.cpp + * - https://github.com/mamedev/mame/blob/master/src/devices/machine/ncr53c90.cpp */ #ifndef MAME_MACHINE_SPIFI3_H diff --git a/src/devices/machine/sun4c_mmu.cpp b/src/devices/machine/sun4c_mmu.cpp index 3ac3645d32f..12e1f0ceae6 100644 --- a/src/devices/machine/sun4c_mmu.cpp +++ b/src/devices/machine/sun4c_mmu.cpp @@ -533,7 +533,7 @@ uint32_t sun4_mmu_base_device::insn_data_r(const uint32_t offset, const uint32_t } // it's translation time - const uint32_t pmeg = m_curr_segmap_masked[(offset >> 16) & 0xfff];// & m_pmeg_mask; + const uint32_t pmeg = m_curr_segmap_masked[(offset >> 16) & 0xfff]; const uint32_t entry_index = pmeg | ((offset >> m_seg_entry_shift) & m_seg_entry_mask); if (m_page_valid[entry_index]) @@ -684,21 +684,16 @@ void sun4_mmu_base_device::insn_data_w(const uint32_t offset, const uint32_t dat void sun4_mmu_base_device::l2p_command(const std::vector ¶ms) { - uint64_t addr, offset; - + uint64_t addr; if (!machine().debugger().console().validate_number_parameter(params[0], addr)) return; addr &= 0xffffffff; - offset = addr >> 2; + uint64_t offset = addr >> 2; - uint8_t pmeg = 0; - uint32_t entry_index = 0, tmp = 0; - uint32_t entry_value = 0; - - pmeg = m_curr_segmap_masked[(offset >> 16) & 0xfff]; - entry_index = pmeg | ((offset >> m_seg_entry_shift) & m_seg_entry_mask); - tmp = m_pagemap[entry_index].page | (offset & m_page_mask); - entry_value = page_entry_to_uint(entry_index); + const uint32_t pmeg = m_curr_segmap_masked[(offset >> 16) & 0xfff]; + const uint32_t entry_index = pmeg | ((offset >> m_seg_entry_shift) & m_seg_entry_mask); + const uint32_t tmp = m_pagemap[entry_index].page | (offset & m_page_mask); + const uint32_t entry_value = page_entry_to_uint(entry_index); if (m_page_valid[entry_index]) { @@ -706,7 +701,7 @@ void sun4_mmu_base_device::l2p_command(const std::vector ¶ } else { - machine().debugger().console().printf("logical %08x points to an invalid PTE! (pmeg %d, entry %d PTE %08x)\n", addr, tmp << 2, pmeg, entry_index, entry_value); + machine().debugger().console().printf("logical %08x points to an invalid PTE! (tmp %08x, pmeg %d, entry %d PTE %08x)\n", addr, tmp << 2, pmeg, entry_index, entry_value); } } diff --git a/src/mame/apple/macpdm.cpp b/src/mame/apple/macpdm.cpp index ab5aad7aae6..19e11ad9e80 100644 --- a/src/mame/apple/macpdm.cpp +++ b/src/mame/apple/macpdm.cpp @@ -11,7 +11,7 @@ #include "cuda.h" #include "macadb.h" #include "machine/mv_sonora.h" -#include "machine/ncr5390.h" +#include "machine/ncr53c90.h" #include "machine/ram.h" #include "machine/swim3.h" #include "machine/timer.h" diff --git a/src/mame/apple/macquadra700.cpp b/src/mame/apple/macquadra700.cpp index e4de4f02fc9..ba52c2e8f71 100644 --- a/src/mame/apple/macquadra700.cpp +++ b/src/mame/apple/macquadra700.cpp @@ -23,7 +23,7 @@ #include "machine/6522via.h" #include "machine/applefdintf.h" #include "machine/dp83932c.h" -#include "machine/ncr5390.h" +#include "machine/ncr53c90.h" #include "machine/nscsi_bus.h" #include "machine/ram.h" #include "machine/swim1.h" diff --git a/src/mame/dec/decstation.cpp b/src/mame/dec/decstation.cpp index 5a3920c231a..981e386e930 100644 --- a/src/mame/dec/decstation.cpp +++ b/src/mame/dec/decstation.cpp @@ -64,7 +64,7 @@ #include "decioga.h" #include "machine/mc146818.h" #include "machine/z80scc.h" -#include "machine/ncr5390.h" +#include "machine/ncr53c90.h" //#include "machine/dc7061.h" #include "machine/nscsi_bus.h" #include "bus/nscsi/cd.h" diff --git a/src/mame/intergraph/interpro.cpp b/src/mame/intergraph/interpro.cpp index 3ca5c542805..ec5b0d67590 100644 --- a/src/mame/intergraph/interpro.cpp +++ b/src/mame/intergraph/interpro.cpp @@ -243,7 +243,7 @@ #include "machine/upd765.h" #include "machine/i82586.h" -#include "machine/ncr5390.h" +#include "machine/ncr53c90.h" #include "machine/nscsi_bus.h" #include "bus/nscsi/cd.h" #include "bus/nscsi/hd.h" @@ -1126,7 +1126,7 @@ static void interpro_scsi_devices(device_slot_interface &device) void interpro_state::interpro_scsi_adapter(device_t *device) { - ncr5390_device &adapter = downcast(*device); + ncr53c90_device &adapter = downcast(*device); adapter.set_clock(24_MHz_XTAL); diff --git a/src/mame/microsoft/jazz.cpp b/src/mame/microsoft/jazz.cpp index b8afc332667..4be1363858c 100644 --- a/src/mame/microsoft/jazz.cpp +++ b/src/mame/microsoft/jazz.cpp @@ -68,7 +68,7 @@ #include "machine/dp83932c.h" #include "machine/mc146818.h" #include "machine/ins8250.h" -#include "machine/ncr5390.h" +#include "machine/ncr53c90.h" #include "machine/upd765.h" #include "machine/at_keybc.h" #include "machine/pc_lpt.h" diff --git a/src/mame/mips/mips.cpp b/src/mame/mips/mips.cpp index 99fb749196b..7e5c6908c8a 100644 --- a/src/mame/mips/mips.cpp +++ b/src/mame/mips/mips.cpp @@ -218,7 +218,7 @@ // i/o devices (rx3230) #include "machine/timekpr.h" -#include "machine/ncr5390.h" +#include "machine/ncr53c90.h" #include "mips_rambo.h" // busses and connectors diff --git a/src/mame/nec/ews4800.cpp b/src/mame/nec/ews4800.cpp index 02e69638274..71f12c802df 100644 --- a/src/mame/nec/ews4800.cpp +++ b/src/mame/nec/ews4800.cpp @@ -22,7 +22,7 @@ #include "machine/z80scc.h" #include "machine/am79c90.h" #include "machine/timekpr.h" -#include "machine/ncr5390.h" +#include "machine/ncr53c90.h" // busses and connectors #include "machine/nscsi_bus.h" diff --git a/src/mame/next/next.cpp b/src/mame/next/next.cpp index 9b862594bb9..07d59227658 100644 --- a/src/mame/next/next.cpp +++ b/src/mame/next/next.cpp @@ -583,7 +583,7 @@ void next_state::scsictrl_w(offs_t offset, uint32_t data, uint32_t mem_mask) scsictrl & 0x08 ? "read" : "write", scsictrl & 0x04 ? " flush" : "", scsictrl & 0x02 ? " reset" : "", - scsictrl & 0x01 ? "wd3392" : "ncr5390", + scsictrl & 0x01 ? "wd3392" : "ncr53c90", maincpu->pc()); } if(ACCESSING_BITS_16_23) { @@ -912,7 +912,7 @@ void next_state::next_mem(address_map &map) map(0x0200e000, 0x0200e00b).mirror(0x300000).m(keyboard, FUNC(nextkbd_device::amap)); // map(0x0200f000, 0x0200f003).mirror(0x300000); printer // map(0x02010000, 0x02010003).mirror(0x300000); brightness - map(0x02014000, 0x0201400f).mirror(0x300000).m(scsi, FUNC(ncr5390_device::map)); + map(0x02014000, 0x0201400f).mirror(0x300000).m(scsi, FUNC(ncr53c90_device::map)); map(0x02014020, 0x02014023).mirror(0x300000).rw(FUNC(next_state::scsictrl_r), FUNC(next_state::scsictrl_w)); map(0x02016000, 0x02016003).mirror(0x300000).rw(FUNC(next_state::timer_data_r), FUNC(next_state::timer_data_w)); map(0x02016004, 0x02016007).mirror(0x300000).rw(FUNC(next_state::timer_ctrl_r), FUNC(next_state::timer_ctrl_w)); @@ -1015,12 +1015,12 @@ static void next_scsi_devices(device_slot_interface &device) { device.option_add("cdrom", NSCSI_CDROM); device.option_add("harddisk", NSCSI_HARDDISK); - device.option_add_internal("ncr5390", NCR5390); + device.option_add_internal("ncr53c90", NCR53C90); } -void next_state::ncr5390(device_t *device) +void next_state::ncr53c90(device_t *device) { - ncr5390_device &adapter = downcast(*device); + ncr53c90_device &adapter = downcast(*device); adapter.set_clock(10000000); adapter.irq_handler_cb().set(*this, FUNC(next_state::scsi_irq)); @@ -1058,7 +1058,7 @@ void next_state::next_base(machine_config &config) NSCSI_CONNECTOR(config, "scsibus:4", next_scsi_devices, nullptr); NSCSI_CONNECTOR(config, "scsibus:5", next_scsi_devices, nullptr); NSCSI_CONNECTOR(config, "scsibus:6", next_scsi_devices, nullptr); - NSCSI_CONNECTOR(config, "scsibus:7", next_scsi_devices, "ncr5390", true).set_option_machine_config("ncr5390", [this] (device_t *device) { ncr5390(device); }); + NSCSI_CONNECTOR(config, "scsibus:7", next_scsi_devices, "ncr53c90", true).set_option_machine_config("ncr53c90", [this] (device_t *device) { ncr53c90(device); }); MB8795(config, net, 0); net->tx_irq().set(FUNC(next_state::net_tx_irq)); diff --git a/src/mame/next/next.h b/src/mame/next/next.h index 99d8a79202e..87ca987a7a1 100644 --- a/src/mame/next/next.h +++ b/src/mame/next/next.h @@ -13,7 +13,7 @@ #include "machine/8530scc.h" #include "nextkbd.h" #include "machine/upd765.h" -#include "machine/ncr5390.h" +#include "machine/ncr53c90.h" #include "machine/mb8795.h" #include "nextmo.h" #include "imagedev/chd_cd.h" @@ -29,7 +29,7 @@ public: scc(*this, "scc"), keyboard(*this, "keyboard"), scsibus(*this, "scsibus"), - scsi(*this, "scsibus:7:ncr5390"), + scsi(*this, "scsibus:7:ncr53c90"), net(*this, "net"), mo(*this, "mo"), fdc(*this, "fdc"), @@ -68,7 +68,7 @@ private: required_device scc; required_device keyboard; required_device scsibus; - required_device scsi; + required_device scsi; required_device net; optional_device mo; // cube only optional_device fdc; // 040 only @@ -146,7 +146,7 @@ private: DECLARE_WRITE_LINE_MEMBER(vblank_w); - void ncr5390(device_t *device); + void ncr53c90(device_t *device); void next_0b_m_mem(address_map &map); void next_0b_m_mo_mem(address_map &map); void next_0b_m_nofdc_mem(address_map &map); diff --git a/src/mame/sun/sun4.cpp b/src/mame/sun/sun4.cpp index 0791955f03d..7b7ff18331a 100644 --- a/src/mame/sun/sun4.cpp +++ b/src/mame/sun/sun4.cpp @@ -422,7 +422,7 @@ #include "imagedev/floppy.h" #include "machine/am79c90.h" #include "machine/bankdev.h" -#include "machine/ncr5390.h" +#include "machine/ncr53c90.h" #include "machine/nscsi_bus.h" #include "machine/nvram.h" #include "machine/ram.h" @@ -558,7 +558,7 @@ public: , m_floppy(*this, "fdc:0") , m_lance(*this, "lance") , m_scsibus(*this, "scsibus") - , m_scsi(*this, "scsibus:7:ncr53c90a") + , m_scsi(*this, "scsibus:7:ncr53c90") , m_type1space(*this, "type1") , m_ram(*this, RAM_TAG) , m_rom(*this, "user1") @@ -601,7 +601,7 @@ protected: DECLARE_WRITE_LINE_MEMBER(fdc_irq); - void ncr53c90a(device_t *device); + void ncr53c90(device_t *device); void debugger_map(address_map &map); void system_asi_map(address_map &map); @@ -636,7 +636,7 @@ protected: required_device m_floppy; required_device m_lance; required_device m_scsibus; - required_device m_scsi; + required_device m_scsi; required_device m_type1space; required_device m_ram; @@ -776,7 +776,7 @@ void sun4_base_state::type1space_base_map(address_map &map) map(0x08400000, 0x08400003).rw(FUNC(sun4_base_state::dma_ctrl_r), FUNC(sun4_base_state::dma_ctrl_w)); map(0x08400004, 0x08400007).rw(FUNC(sun4_base_state::dma_addr_r), FUNC(sun4_base_state::dma_addr_w)); map(0x08400008, 0x0840000b).rw(FUNC(sun4_base_state::dma_count_r), FUNC(sun4_base_state::dma_count_w)); - map(0x08800000, 0x0880002f).m(m_scsi, FUNC(ncr53c90a_device::map)).umask32(0xff000000); + map(0x08800000, 0x0880002f).m(m_scsi, FUNC(ncr53c90_device::map)).umask32(0xff000000); map(0x08c00000, 0x08c00003).rw(m_lance, FUNC(am79c90_device::regs_r), FUNC(am79c90_device::regs_w)); } @@ -1244,7 +1244,7 @@ u32 sun4_base_state::dma_ctrl_r() dma_check_interrupts(); } LOGMASKED(LOG_DMA_CTRL_READS, "%s: dma_ctrl_r: %08x\n", machine().describe_context(), m_dma_ctrl); - return m_dma_ctrl; + return (m_dma_ctrl & ~(DMA_WRITE_ONLY | DMA_BYTE_ADDR)) | DMA_DEV_ID; } u32 sun4_base_state::dma_addr_r() @@ -1292,6 +1292,7 @@ void sun4_base_state::dma_ctrl_w(offs_t offset, u32 data, u32 mem_mask) m_dma_addr++; } m_dma_pack_register = 0; + m_dma_ctrl &= ~DMA_PACK_CNT; } @@ -1369,13 +1370,13 @@ static void sun_scsi_devices(device_slot_interface &device) { device.option_add("cdrom", NSCSI_CDROM); device.option_add("harddisk", NSCSI_HARDDISK); - device.option_add_internal("ncr53c90a", NCR53C90A); + device.option_add_internal("ncr53c90", NCR53C90); device.set_option_machine_config("cdrom", sun4_cdrom); } -void sun4_base_state::ncr53c90a(device_t *device) +void sun4_base_state::ncr53c90(device_t *device) { - ncr53c90a_device &adapter = downcast(*device); + ncr53c90_device &adapter = downcast(*device); adapter.set_clock(10000000); adapter.irq_handler_cb().set(*this, FUNC(sun4_base_state::scsi_irq)); @@ -1443,7 +1444,7 @@ void sun4_base_state::sun4_base(machine_config &config) NSCSI_CONNECTOR(config, "scsibus:4", sun_scsi_devices, nullptr); NSCSI_CONNECTOR(config, "scsibus:5", sun_scsi_devices, nullptr); NSCSI_CONNECTOR(config, "scsibus:6", sun_scsi_devices, "cdrom"); - NSCSI_CONNECTOR(config, "scsibus:7", sun_scsi_devices, "ncr53c90a", true).set_option_machine_config("ncr53c90a", [this] (device_t *device) { ncr53c90a(device); }); + NSCSI_CONNECTOR(config, "scsibus:7", sun_scsi_devices, "ncr53c90", true).set_option_machine_config("ncr53c90", [this] (device_t *device) { ncr53c90(device); }); } void sun4_state::sun4(machine_config &config) -- cgit v1.2.3