mirror of
https://github.com/holub/mame
synced 2025-04-22 16:31:49 +03:00
New S-100 device: ASC Associates SASI Host Computer Adapter [AJR, Bitsavers]
This commit is contained in:
parent
05d6c01a48
commit
efbe4b30ba
@ -1796,6 +1796,8 @@ if (BUSES["S100"]~=null) then
|
||||
MAME_DIR .. "src/devices/bus/s100/s100.h",
|
||||
MAME_DIR .. "src/devices/bus/s100/am310.cpp",
|
||||
MAME_DIR .. "src/devices/bus/s100/am310.h",
|
||||
MAME_DIR .. "src/devices/bus/s100/ascsasi.cpp",
|
||||
MAME_DIR .. "src/devices/bus/s100/ascsasi.h",
|
||||
MAME_DIR .. "src/devices/bus/s100/dg640.cpp",
|
||||
MAME_DIR .. "src/devices/bus/s100/dg640.h",
|
||||
MAME_DIR .. "src/devices/bus/s100/dj2db.cpp",
|
||||
|
362
src/devices/bus/s100/ascsasi.cpp
Normal file
362
src/devices/bus/s100/ascsasi.cpp
Normal file
@ -0,0 +1,362 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:AJR
|
||||
/**********************************************************************
|
||||
|
||||
ASC Associates SASI Host Computer Adapter
|
||||
|
||||
This is a simple host adapter using LSTTL latches and buffers to
|
||||
interface a SASI Winchester drive to the S-100 bus. The 2716 PROM
|
||||
contains 8080 bootstrap code for a CP/M system.
|
||||
|
||||
For a technical description of this board by its designers, see
|
||||
"Building a Hard-Disk Interface for a S-100 Bus System" by Andrew
|
||||
C. Cruce and Scott A. Alexander in the March, April and May 1983
|
||||
issues of BYTE magazine. (The schematic diagrams contain various
|
||||
minor errors.)
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "ascsasi.h"
|
||||
|
||||
#include "bus/nscsi/devices.h"
|
||||
#include "machine/nscsi_bus.h"
|
||||
#include "machine/nscsi_cb.h"
|
||||
|
||||
class asc_sasi_device : public device_t, public device_s100_card_interface
|
||||
{
|
||||
// N.B. actual pulse widths depend on S-100 bus characteristics
|
||||
static constexpr attotime s_pulse_width = attotime::from_nsec(500);
|
||||
|
||||
public:
|
||||
// construction/destruction
|
||||
asc_sasi_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
virtual ioport_constructor device_input_ports() const override;
|
||||
virtual void device_add_mconfig(machine_config &config) override;
|
||||
virtual const tiny_rom_entry *device_rom_region() const override;
|
||||
|
||||
// device_s100_card_interface overrides
|
||||
virtual u8 s100_smemr_r(offs_t offset) override;
|
||||
virtual u8 s100_sinp_r(offs_t offset) override;
|
||||
virtual void s100_sout_w(offs_t offset, u8 data) override;
|
||||
|
||||
private:
|
||||
DECLARE_WRITE_LINE_MEMBER(iio_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(req_w);
|
||||
void sasi_sel_pulse();
|
||||
void sasi_rst_pulse();
|
||||
TIMER_CALLBACK_MEMBER(sel_off);
|
||||
TIMER_CALLBACK_MEMBER(rst_off);
|
||||
|
||||
// object finders
|
||||
required_device<nscsi_bus_device> m_sasi;
|
||||
required_region_ptr<u8> m_bootstrap;
|
||||
required_ioport m_memsel;
|
||||
required_ioport m_iosel;
|
||||
|
||||
// pulse timers
|
||||
emu_timer *m_sel_off_timer;
|
||||
emu_timer *m_rst_off_timer;
|
||||
|
||||
// internal state
|
||||
u8 m_data_latch;
|
||||
bool m_boot;
|
||||
};
|
||||
|
||||
constexpr attotime asc_sasi_device::s_pulse_width; // stupid non-inline semantics
|
||||
|
||||
DEFINE_DEVICE_TYPE_PRIVATE(S100_ASC_SASI, device_s100_card_interface, asc_sasi_device, "ascsasi", "ASC Associates SASI Host Computer Adapter")
|
||||
|
||||
asc_sasi_device::asc_sasi_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
|
||||
: device_t(mconfig, S100_ASC_SASI, tag, owner, clock)
|
||||
, device_s100_card_interface(mconfig, *this)
|
||||
, m_sasi(*this, "sasi")
|
||||
, m_bootstrap(*this, "bootstrap")
|
||||
, m_memsel(*this, "MEMSEL")
|
||||
, m_iosel(*this, "IOSEL")
|
||||
, m_sel_off_timer(nullptr)
|
||||
, m_rst_off_timer(nullptr)
|
||||
, m_data_latch(0)
|
||||
, m_boot(false)
|
||||
{
|
||||
}
|
||||
|
||||
void asc_sasi_device::device_start()
|
||||
{
|
||||
// initialize timers
|
||||
m_sel_off_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(asc_sasi_device::sel_off), this));
|
||||
m_rst_off_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(asc_sasi_device::rst_off), this));
|
||||
|
||||
// save state
|
||||
save_item(NAME(m_data_latch));
|
||||
save_item(NAME(m_boot));
|
||||
}
|
||||
|
||||
void asc_sasi_device::device_reset()
|
||||
{
|
||||
// POC causes RST pulse on SASI bus (unless jumper is removed)
|
||||
sasi_rst_pulse();
|
||||
|
||||
// CLR sets flip-flop (IC10a)
|
||||
m_boot = true;
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(asc_sasi_device::iio_w)
|
||||
{
|
||||
// Release data bus when I/O is asserted
|
||||
if (state)
|
||||
m_sasi->data_w(7, 0);
|
||||
else
|
||||
m_sasi->data_w(7, m_data_latch);
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(asc_sasi_device::req_w)
|
||||
{
|
||||
// Clear ACK when REQ is negated
|
||||
if (!state)
|
||||
m_sasi->ctrl_w(7, 0, nscsi_device::S_ACK);
|
||||
}
|
||||
|
||||
void asc_sasi_device::sasi_sel_pulse()
|
||||
{
|
||||
m_sel_off_timer->adjust(s_pulse_width);
|
||||
}
|
||||
|
||||
void asc_sasi_device::sasi_rst_pulse()
|
||||
{
|
||||
m_rst_off_timer->adjust(s_pulse_width);
|
||||
}
|
||||
|
||||
TIMER_CALLBACK_MEMBER(asc_sasi_device::sel_off)
|
||||
{
|
||||
}
|
||||
|
||||
TIMER_CALLBACK_MEMBER(asc_sasi_device::rst_off)
|
||||
{
|
||||
}
|
||||
|
||||
u8 asc_sasi_device::s100_smemr_r(offs_t offset)
|
||||
{
|
||||
u8 memsel = m_memsel->read();
|
||||
if (m_boot && BIT(memsel, 0) && (offset & 0xf800) == (memsel & 0x3e) << 10)
|
||||
return m_bootstrap[offset & 0x7ff];
|
||||
else
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
u8 asc_sasi_device::s100_sinp_r(offs_t offset)
|
||||
{
|
||||
// Only two input ports are decoded
|
||||
if ((offset & 0xfe) == (m_iosel->read() & 0x3f) << 2)
|
||||
{
|
||||
if (BIT(offset, 0))
|
||||
{
|
||||
// 74LS240 buffer (IC7)
|
||||
u32 ctrl = m_sasi->ctrl_r();
|
||||
return (ctrl & nscsi_device::S_INP ? 0x01 : 0x00)
|
||||
| (ctrl & nscsi_device::S_BSY ? 0x04 : 0x00)
|
||||
| (ctrl & nscsi_device::S_REQ ? 0x10 : 0x00)
|
||||
| (ctrl & nscsi_device::S_CTL ? 0x80 : 0x00);
|
||||
}
|
||||
else
|
||||
{
|
||||
// INDAT: 74LS240 buffer (IC13)
|
||||
if (!machine().side_effects_disabled() && (m_sasi->ctrl_r() && nscsi_device::S_REQ))
|
||||
m_sasi->ctrl_w(7, nscsi_device::S_ACK, nscsi_device::S_ACK);
|
||||
return m_sasi->data_r();
|
||||
}
|
||||
}
|
||||
else
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
void asc_sasi_device::s100_sout_w(offs_t offset, u8 data)
|
||||
{
|
||||
if ((offset & 0xfc) == (m_iosel->read() & 0x3f) << 2)
|
||||
{
|
||||
switch (offset & 0x03)
|
||||
{
|
||||
case 0:
|
||||
// LATENA: 74LS373 latch (IC8) outputs to 74LS240 buffer (IC9)
|
||||
if (!machine().side_effects_disabled() && (m_sasi->ctrl_r() && nscsi_device::S_REQ))
|
||||
m_sasi->ctrl_w(7, nscsi_device::S_ACK, nscsi_device::S_ACK);
|
||||
m_data_latch = data;
|
||||
if (!(m_sasi->ctrl_r() && nscsi_device::S_INP))
|
||||
m_sasi->data_w(7, data);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
sasi_sel_pulse();
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// MEMCON: clock DO5 into flip-flop (IC10a)
|
||||
m_boot = BIT(data, 5);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
sasi_rst_pulse();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static INPUT_PORTS_START(ascsasi)
|
||||
PORT_START("MEMSEL")
|
||||
PORT_DIPNAME(0x01, 0x01, "Bootstrap PROM")
|
||||
PORT_DIPSETTING(0x00, DEF_STR(Off))
|
||||
PORT_DIPSETTING(0x01, DEF_STR(On))
|
||||
PORT_DIPNAME(0x3e, 0x38, "PROM Address Decode") PORT_DIPLOCATION("SW1:2,3,4,5,6")
|
||||
PORT_DIPSETTING(0x00, "0000-07FF")
|
||||
PORT_DIPSETTING(0x02, "0800-0FFF")
|
||||
PORT_DIPSETTING(0x04, "1000-17FF")
|
||||
PORT_DIPSETTING(0x06, "1800-1FFF")
|
||||
PORT_DIPSETTING(0x08, "2000-27FF")
|
||||
PORT_DIPSETTING(0x0a, "2800-2FFF")
|
||||
PORT_DIPSETTING(0x0c, "3000-37FF")
|
||||
PORT_DIPSETTING(0x0e, "3800-3FFF")
|
||||
PORT_DIPSETTING(0x10, "4000-47FF")
|
||||
PORT_DIPSETTING(0x12, "4800-4FFF")
|
||||
PORT_DIPSETTING(0x14, "5000-57FF")
|
||||
PORT_DIPSETTING(0x16, "5800-5FFF")
|
||||
PORT_DIPSETTING(0x18, "6000-67FF")
|
||||
PORT_DIPSETTING(0x1a, "6800-6FFF")
|
||||
PORT_DIPSETTING(0x1c, "7000-77FF")
|
||||
PORT_DIPSETTING(0x1e, "7800-7FFF")
|
||||
PORT_DIPSETTING(0x20, "8000-87FF")
|
||||
PORT_DIPSETTING(0x22, "8800-8FFF")
|
||||
PORT_DIPSETTING(0x24, "9000-97FF")
|
||||
PORT_DIPSETTING(0x26, "9800-9FFF")
|
||||
PORT_DIPSETTING(0x28, "A000-A7FF")
|
||||
PORT_DIPSETTING(0x2a, "A800-AFFF")
|
||||
PORT_DIPSETTING(0x2c, "B000-B7FF")
|
||||
PORT_DIPSETTING(0x2e, "B800-BFFF")
|
||||
PORT_DIPSETTING(0x30, "C000-C7FF")
|
||||
PORT_DIPSETTING(0x32, "C800-CFFF")
|
||||
PORT_DIPSETTING(0x34, "D000-D7FF")
|
||||
PORT_DIPSETTING(0x36, "D800-DFFF")
|
||||
PORT_DIPSETTING(0x38, "E000-E7FF")
|
||||
PORT_DIPSETTING(0x3a, "E800-EFFF")
|
||||
PORT_DIPSETTING(0x3c, "F000-F7FF")
|
||||
PORT_DIPSETTING(0x3e, "F800-FFFF")
|
||||
PORT_DIPNAME(0x40, 0x40, "PHANTOM Signal") PORT_DIPLOCATION("SW1:7") // not emulated
|
||||
PORT_DIPSETTING(0x40, DEF_STR(Off))
|
||||
PORT_DIPSETTING(0x00, DEF_STR(On))
|
||||
PORT_DIPNAME(0x80, 0x80, "Memory Wait State") PORT_DIPLOCATION("SW1:8") // not emulated
|
||||
PORT_DIPSETTING(0x80, DEF_STR(Off))
|
||||
PORT_DIPSETTING(0x00, DEF_STR(On))
|
||||
|
||||
PORT_START("IOSEL")
|
||||
PORT_DIPNAME(0x3f, 0x28, "I/O Address Decode") PORT_DIPLOCATION("SW2:1,2,3,4,5,6")
|
||||
PORT_DIPSETTING(0x00, "00-03")
|
||||
PORT_DIPSETTING(0x01, "04-07")
|
||||
PORT_DIPSETTING(0x02, "08-0B")
|
||||
PORT_DIPSETTING(0x03, "0C-0F")
|
||||
PORT_DIPSETTING(0x04, "10-13")
|
||||
PORT_DIPSETTING(0x05, "14-17")
|
||||
PORT_DIPSETTING(0x06, "18-1B")
|
||||
PORT_DIPSETTING(0x07, "1C-1F")
|
||||
PORT_DIPSETTING(0x08, "20-23")
|
||||
PORT_DIPSETTING(0x09, "24-27")
|
||||
PORT_DIPSETTING(0x0a, "28-2B")
|
||||
PORT_DIPSETTING(0x0b, "2C-2F")
|
||||
PORT_DIPSETTING(0x0c, "30-33")
|
||||
PORT_DIPSETTING(0x0d, "34-37")
|
||||
PORT_DIPSETTING(0x0e, "38-3B")
|
||||
PORT_DIPSETTING(0x0f, "3C-3F")
|
||||
PORT_DIPSETTING(0x10, "40-43")
|
||||
PORT_DIPSETTING(0x11, "44-47")
|
||||
PORT_DIPSETTING(0x12, "48-4B")
|
||||
PORT_DIPSETTING(0x13, "4C-4F")
|
||||
PORT_DIPSETTING(0x14, "50-53")
|
||||
PORT_DIPSETTING(0x15, "54-57")
|
||||
PORT_DIPSETTING(0x16, "58-5B")
|
||||
PORT_DIPSETTING(0x17, "5C-5F")
|
||||
PORT_DIPSETTING(0x18, "60-63")
|
||||
PORT_DIPSETTING(0x19, "64-67")
|
||||
PORT_DIPSETTING(0x1a, "68-6B")
|
||||
PORT_DIPSETTING(0x1b, "6C-6F")
|
||||
PORT_DIPSETTING(0x1c, "70-73")
|
||||
PORT_DIPSETTING(0x1d, "74-77")
|
||||
PORT_DIPSETTING(0x1e, "78-7B")
|
||||
PORT_DIPSETTING(0x1f, "7C-7F")
|
||||
PORT_DIPSETTING(0x20, "80-83")
|
||||
PORT_DIPSETTING(0x21, "84-87")
|
||||
PORT_DIPSETTING(0x22, "88-8B")
|
||||
PORT_DIPSETTING(0x23, "8C-8F")
|
||||
PORT_DIPSETTING(0x24, "90-93")
|
||||
PORT_DIPSETTING(0x25, "94-97")
|
||||
PORT_DIPSETTING(0x26, "98-9B")
|
||||
PORT_DIPSETTING(0x27, "9C-9F")
|
||||
PORT_DIPSETTING(0x28, "A0-A3")
|
||||
PORT_DIPSETTING(0x29, "A4-A7")
|
||||
PORT_DIPSETTING(0x2a, "A8-AB")
|
||||
PORT_DIPSETTING(0x2b, "AC-AF")
|
||||
PORT_DIPSETTING(0x2c, "B0-B3")
|
||||
PORT_DIPSETTING(0x2d, "B4-B7")
|
||||
PORT_DIPSETTING(0x2e, "B8-BB")
|
||||
PORT_DIPSETTING(0x2f, "BC-BF")
|
||||
PORT_DIPSETTING(0x30, "C0-C3")
|
||||
PORT_DIPSETTING(0x31, "C4-C7")
|
||||
PORT_DIPSETTING(0x32, "C8-CB")
|
||||
PORT_DIPSETTING(0x33, "CC-CF")
|
||||
PORT_DIPSETTING(0x34, "D0-D3")
|
||||
PORT_DIPSETTING(0x35, "D4-D7")
|
||||
PORT_DIPSETTING(0x36, "D8-DB")
|
||||
PORT_DIPSETTING(0x37, "DC-DF")
|
||||
PORT_DIPSETTING(0x38, "E0-E3")
|
||||
PORT_DIPSETTING(0x39, "E4-E7")
|
||||
PORT_DIPSETTING(0x3a, "E8-EB")
|
||||
PORT_DIPSETTING(0x3b, "EC-EF")
|
||||
PORT_DIPSETTING(0x3c, "F0-F3")
|
||||
PORT_DIPSETTING(0x3d, "F4-F7")
|
||||
PORT_DIPSETTING(0x3e, "F8-FB")
|
||||
PORT_DIPSETTING(0x3f, "FC-FF")
|
||||
PORT_DIPNAME(0x40, 0x40, DEF_STR(Unused)) PORT_DIPLOCATION("SW2:7")
|
||||
PORT_DIPSETTING(0x40, DEF_STR(Off))
|
||||
PORT_DIPSETTING(0x00, DEF_STR(On))
|
||||
PORT_DIPNAME(0x80, 0x80, DEF_STR(Unused)) PORT_DIPLOCATION("SW2:8")
|
||||
PORT_DIPSETTING(0x80, DEF_STR(Off))
|
||||
PORT_DIPSETTING(0x00, DEF_STR(On))
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
ioport_constructor asc_sasi_device::device_input_ports() const
|
||||
{
|
||||
return INPUT_PORTS_NAME(ascsasi);
|
||||
}
|
||||
|
||||
void asc_sasi_device::device_add_mconfig(machine_config &config)
|
||||
{
|
||||
NSCSI_BUS(config, m_sasi);
|
||||
NSCSI_CONNECTOR(config, "sasi:0", default_scsi_devices, nullptr);
|
||||
NSCSI_CONNECTOR(config, "sasi:1", default_scsi_devices, nullptr);
|
||||
NSCSI_CONNECTOR(config, "sasi:2", default_scsi_devices, nullptr);
|
||||
NSCSI_CONNECTOR(config, "sasi:3", default_scsi_devices, nullptr);
|
||||
NSCSI_CONNECTOR(config, "sasi:4", default_scsi_devices, nullptr);
|
||||
NSCSI_CONNECTOR(config, "sasi:5", default_scsi_devices, nullptr);
|
||||
NSCSI_CONNECTOR(config, "sasi:6", default_scsi_devices, nullptr);
|
||||
NSCSI_CONNECTOR(config, "sasi:7", default_scsi_devices, "sasicb", true)
|
||||
.option_add_internal("sasicb", NSCSI_CB)
|
||||
.machine_config([this] (device_t *device) {
|
||||
downcast<nscsi_callback_device &>(*device).io_callback().set(*this, FUNC(asc_sasi_device::iio_w));
|
||||
downcast<nscsi_callback_device &>(*device).req_callback().set(*this, FUNC(asc_sasi_device::req_w));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
ROM_START(ascsasi)
|
||||
ROM_REGION(0x800, "bootstrap", 0)
|
||||
ROM_LOAD("asc_sasi.bin", 0x000, 0x800, CRC(aac84077) SHA1(e94b39875e29daff199d120c4e79dfb1adbedab2)) // MODEL 1 REV. 2
|
||||
ROM_END
|
||||
|
||||
const tiny_rom_entry *asc_sasi_device::device_rom_region() const
|
||||
{
|
||||
return ROM_NAME(ascsasi);
|
||||
}
|
18
src/devices/bus/s100/ascsasi.h
Normal file
18
src/devices/bus/s100/ascsasi.h
Normal file
@ -0,0 +1,18 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:AJR
|
||||
/**********************************************************************
|
||||
|
||||
ASC Associates SASI Host Computer Adapter
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef MAME_BUS_S100_ASCSASI_H
|
||||
#define MAME_BUS_S100_ASCSASI_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "bus/s100/s100.h"
|
||||
|
||||
DECLARE_DEVICE_TYPE(S100_ASC_SASI, device_s100_card_interface)
|
||||
|
||||
#endif // MAME_BUS_S100_ASCSASI_H
|
@ -48,6 +48,7 @@ at least some models of the Poly-88 are known to have used.)
|
||||
#include "emu.h"
|
||||
#include "includes/poly88.h"
|
||||
|
||||
#include "bus/s100/ascsasi.h"
|
||||
#include "bus/s100/poly16k.h"
|
||||
#include "bus/s100/polyfdc.h"
|
||||
#include "bus/s100/polyvti.h"
|
||||
@ -107,6 +108,7 @@ static void poly88_s100_devices(device_slot_interface &device)
|
||||
device.option_add("8kscbb", S100_8K_SC_BB);
|
||||
device.option_add("poly16k", S100_POLY_16K);
|
||||
device.option_add("polyfdc", S100_POLY_FDC);
|
||||
device.option_add("ascsasi", S100_ASC_SASI);
|
||||
}
|
||||
|
||||
DEVICE_INPUT_DEFAULTS_START(poly88_vti_1800)
|
||||
|
Loading…
Reference in New Issue
Block a user