summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices
diff options
context:
space:
mode:
author arbee <rb6502@users.noreply.github.com>2020-09-20 22:41:42 -0400
committer arbee <rb6502@users.noreply.github.com>2020-09-20 22:41:42 -0400
commitd3138d7dd41e85504d4f99788b5ddab0f2294039 (patch)
tree93d3f866c2dacecee7aeb76020081613caf74328 /src/devices
parent6eaa5f09467165e144da9369dc51aa6cfc500cd0 (diff)
apple2: preliminary support for the Sider SASI card and the Xebec OEM version [R. Belmont]
Diffstat (limited to 'src/devices')
-rw-r--r--src/devices/bus/a2bus/sider.cpp277
-rw-r--r--src/devices/bus/a2bus/sider.h77
2 files changed, 354 insertions, 0 deletions
diff --git a/src/devices/bus/a2bus/sider.cpp b/src/devices/bus/a2bus/sider.cpp
new file mode 100644
index 00000000000..97826b9b3d5
--- /dev/null
+++ b/src/devices/bus/a2bus/sider.cpp
@@ -0,0 +1,277 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/*********************************************************************
+
+ sider.cpp
+
+ Implementation of the First Class Peripherals / Advanced Tech Services / Xebec SASI Card
+
+ The original card was by Xebec; the Sider's relationship with Xebec is not clear, but
+ the Sider version of the firmware is quite different (and much more compact).
+
+ $C0(n+8)X space:
+ $0: read state / write latch
+ $1: read data / write control
+
+ State:
+ b3: /Busy
+ b4: /Message
+ b5: I/O
+ b6: C/D
+ b7: REQ
+
+ Control:
+ b4: drive contents of output latch onto the SASI bus (reverse logic; latch is driven when this bit is clear)
+ b5: reset bus
+ b6: /BSY
+ b7: /SEL
+
+*********************************************************************/
+
+#include "emu.h"
+#include "sider.h"
+#include "bus/scsi/scsihd.h"
+#include "bus/scsi/s1410.h"
+
+/***************************************************************************
+ PARAMETERS
+***************************************************************************/
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(A2BUS_SIDER, a2bus_sidercard_device, "a2sider", "First Class Peripherals Sider SASI Card")
+DEFINE_DEVICE_TYPE(A2BUS_XEBEC, a2bus_xebeccard_device, "a2xebec", "Xebec SASI Card")
+
+#define SASI_ROM_REGION "sasi_rom"
+
+ROM_START( sider )
+ ROM_REGION(0x800, SASI_ROM_REGION, 0)
+ ROM_LOAD( "atsv22_a02a9baad2262a8a49ecea843f602124.bin", 0x000000, 0x000800, CRC(97773a0b) SHA1(8d0a5d6ce3b9a236771126033c4aba6c0cc5e704) )
+ROM_END
+
+ROM_START( xebec )
+ ROM_REGION(0x800, SASI_ROM_REGION, 0)
+ ROM_LOAD( "xebec-103684c-1986.bin", 0x000000, 0x000800, CRC(9e62e15f) SHA1(7f50b5e00cac4960204f50448a6e2d623b1a41e2) )
+ROM_END
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void a2bus_sider_device::device_add_mconfig(machine_config &config)
+{
+ NSCSI_BUS(config, m_sasibus);
+ NSCSI_CONNECTOR(config, "sasibus:0", default_scsi_devices, "s1410", false);
+ NSCSI_CONNECTOR(config, "sasibus:1", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "sasibus:2", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "sasibus:3", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "sasibus:4", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "sasibus:5", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "sasibus:6", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "sasibus:7", default_scsi_devices, "scsicb", true).option_add_internal("scsicb", NSCSI_CB);
+}
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *a2bus_sidercard_device::device_rom_region() const
+{
+ return ROM_NAME( sider );
+}
+
+const tiny_rom_entry *a2bus_xebeccard_device::device_rom_region() const
+{
+ return ROM_NAME( xebec );
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+a2bus_sider_device::a2bus_sider_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, type, tag, owner, clock),
+ device_a2bus_card_interface(mconfig, *this),
+ m_sasibus(*this, "sasibus"),
+ m_sasi(*this, "sasibus:7:scsicb"),
+ m_rom(*this, SASI_ROM_REGION),
+ m_latch(0xff),
+ m_control(0)
+{
+}
+
+a2bus_sidercard_device::a2bus_sidercard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ a2bus_sider_device(mconfig, A2BUS_SIDER, tag, owner, clock)
+{
+}
+
+a2bus_xebeccard_device::a2bus_xebeccard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ a2bus_sider_device(mconfig, A2BUS_XEBEC, tag, owner, clock)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void a2bus_sider_device::device_start()
+{
+ save_item(NAME(m_latch));
+ save_item(NAME(m_control));
+}
+
+void a2bus_sider_device::device_reset()
+{
+ m_latch = 0xff;
+ m_control = 0;
+}
+
+void a2bus_xebeccard_device::device_start()
+{
+ a2bus_sider_device::device_start();
+
+ m_rom[0x42] = 0x01; // correct boot block jump to $801
+ m_rom[0x492] = 0x01; // correct ProDOS READ_BLOCK to read one block, not two
+ m_rom[0x497] = 0xea; // fix various weird stuff done to the READ_BLOCK parameters
+ m_rom[0x498] = 0xea;
+ m_rom[0x499] = 0xea;
+ m_rom[0x49a] = 0xea;
+ m_rom[0x49b] = 0xea;
+ m_rom[0x49c] = 0xea;
+ m_rom[0x4b4] = 0xea;
+ m_rom[0x4b5] = 0xea;
+ m_rom[0x4b9] = 0xea;
+ m_rom[0x4ba] = 0xea;
+ m_rom[0x4bf] = 0xea;
+ m_rom[0x4c0] = 0xea;
+ m_rom[0x4c7] = 0xea;
+ m_rom[0x4c8] = 0xea;
+ m_rom[0x4c9] = 0xea;
+ m_rom[0x4ca] = 0xea;
+ m_rom[0x4cb] = 0xea;
+ m_rom[0x4cc] = 0xea;
+}
+
+/*-------------------------------------------------
+ read_c0nx - called for reads from this card's c0nx space
+-------------------------------------------------*/
+
+uint8_t a2bus_sider_device::read_c0nx(uint8_t offset)
+{
+ u8 rv = 0;
+
+ switch (offset)
+ {
+ case 0:
+ // b3: /Busy
+ // b4: /Message
+ // b5: I/O
+ // b6: C/D
+ // b7: REQ
+ rv |= m_sasi->req_r() ? 0x80 : 0;
+ rv |= m_sasi->cd_r() ? 0x40 : 0;
+ rv |= m_sasi->io_r() ? 0x20 : 0;
+ rv |= m_sasi->msg_r() ? 0x10 : 0;
+ rv |= m_sasi->bsy_r() ? 0x08 : 0;
+ return rv;
+
+ case 1:
+ rv = m_sasi->read();
+ if ((m_sasi->req_r()) && (m_sasi->io_r()))
+ {
+ m_sasi->ack_w(1);
+ m_sasi->ack_w(0);
+ }
+ return rv;
+
+ default:
+ printf("Read c0n%x (%s)\n", offset, machine().describe_context().c_str());
+ break;
+ }
+
+ return 0xff;
+}
+
+
+/*-------------------------------------------------
+ write_c0nx - called for writes to this card's c0nx space
+-------------------------------------------------*/
+
+void a2bus_sider_device::write_c0nx(uint8_t offset, uint8_t data)
+{
+ switch (offset)
+ {
+ case 0:
+ m_latch = data;
+ if (!(m_control & 0x10))
+ {
+ m_sasi->write(m_latch);
+
+ if (m_sasi->req_r())
+ {
+ m_sasi->ack_w(1);
+ m_sasi->write(0); // stop driving the data lines
+ m_sasi->ack_w(0);
+ }
+ }
+ break;
+
+ case 1:
+// b4: drive contents of output latch onto the SASI bus
+// b5: reset bus
+// b6: /BSY
+// b7: /SEL (error in note on A2DP's schematic; BSY and SEL are the same polarity from the 6502's POV)
+ m_control = data;
+ m_sasi->sel_w((data & 0x80) ? 1 : 0);
+ m_sasi->bsy_w((data & 0x40) ? 1 : 0);
+ if (data & 0x20)
+ {
+ m_sasibus->reset();
+ }
+ else if (!(data & 0x10))
+ {
+ m_sasi->write(m_latch);
+ }
+ break;
+
+ default:
+ printf("Write %02x to c0n%x (%s)\n", data, offset, machine().describe_context().c_str());
+ break;
+ }
+}
+
+/*-------------------------------------------------
+ read_cnxx - called for reads from this card's cnxx space
+-------------------------------------------------*/
+
+uint8_t a2bus_sider_device::read_cnxx(uint8_t offset)
+{
+ // slot images at $700
+ return m_rom[offset + 0x700];
+}
+
+void a2bus_sider_device::write_cnxx(uint8_t offset, uint8_t data)
+{
+}
+
+/*-------------------------------------------------
+ read_c800 - called for reads from this card's c800 space
+-------------------------------------------------*/
+
+uint8_t a2bus_sider_device::read_c800(uint16_t offset)
+{
+ return m_rom[offset];
+}
+
+/*-------------------------------------------------
+ write_c800 - called for writes to this card's c800 space
+-------------------------------------------------*/
+void a2bus_sider_device::write_c800(uint16_t offset, uint8_t data)
+{
+}
diff --git a/src/devices/bus/a2bus/sider.h b/src/devices/bus/a2bus/sider.h
new file mode 100644
index 00000000000..36452c6d3e1
--- /dev/null
+++ b/src/devices/bus/a2bus/sider.h
@@ -0,0 +1,77 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/*********************************************************************
+
+ sider.h
+
+ Implementation of the First Class Peripherals / Advanced Tech Services / Xebec Sider SASI Card
+
+*********************************************************************/
+
+#ifndef MAME_BUS_A2BUS_SIDER_H
+#define MAME_BUS_A2BUS_SIDER_H
+
+#pragma once
+
+#include "a2bus.h"
+#include "bus/nscsi/devices.h"
+#include "machine/nscsi_bus.h"
+#include "machine/nscsi_cb.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class a2bus_sider_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+protected:
+ a2bus_sider_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 void device_add_mconfig(machine_config &config) override;
+
+ // overrides of standard a2bus slot functions
+ virtual uint8_t read_c0nx(uint8_t offset) override;
+ virtual void write_c0nx(uint8_t offset, uint8_t data) override;
+ virtual uint8_t read_cnxx(uint8_t offset) override;
+ virtual void write_cnxx(uint8_t offset, uint8_t data) override;
+ virtual uint8_t read_c800(uint16_t offset) override;
+ virtual void write_c800(uint16_t offset, uint8_t data) override;
+
+ required_device<nscsi_bus_device> m_sasibus;
+ required_device<nscsi_callback_device> m_sasi;
+ required_region_ptr<u8> m_rom;
+
+private:
+ u8 m_latch;
+ u8 m_control;
+};
+
+class a2bus_sidercard_device: public a2bus_sider_device
+{
+public:
+ a2bus_sidercard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ virtual const tiny_rom_entry *device_rom_region() const override;
+};
+
+class a2bus_xebeccard_device: public a2bus_sider_device
+{
+public:
+ a2bus_xebeccard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ // the Xebec version of the firmware doesn't work; it appears to have some bytes corrupted.
+ static constexpr feature_type unemulated_features() { return feature::DISK; }
+
+protected:
+ virtual void device_start() override;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(A2BUS_SIDER, a2bus_sidercard_device)
+DECLARE_DEVICE_TYPE(A2BUS_XEBEC, a2bus_xebeccard_device)
+
+#endif // MAME_BUS_A2BUS_SIDER_H