Add AIC-565 device

This commit is contained in:
AJR 2019-05-06 00:23:55 -04:00
parent 90b6fd0982
commit d3132cc13b
9 changed files with 405 additions and 7 deletions

View File

@ -3895,6 +3895,18 @@ if (MACHINES["SCC2698B"]~=null) then
}
end
---------------------------------------------------
--
--@src/devices/machine/aic565.h,MACHINES["AIC565"] = true
---------------------------------------------------
if (MACHINES["AIC565"]~=null) then
files {
MAME_DIR .. "src/devices/machine/aic565.cpp",
MAME_DIR .. "src/devices/machine/aic565.h",
}
end
---------------------------------------------------
--
--@src/devices/machine/aic6250.h,MACHINES["AIC6250"] = true

View File

@ -660,6 +660,7 @@ MACHINES["PS2INTC"] = true
--MACHINES["IOPINTC"] = true
--MACHINES["IOPSIO2"] = true
--MACHINES["IOPTIMER"] = true
MACHINES["AIC565"] = true
MACHINES["AIC6250"] = true
--------------------------------------------------

View File

@ -691,6 +691,7 @@ MACHINES["IOPINTC"] = true
MACHINES["IOPSIO2"] = true
MACHINES["IOPTIMER"] = true
MACHINES["Z8038"] = true
MACHINES["AIC565"] = true
MACHINES["AIC6250"] = true
MACHINES["DC7085"] = true
MACHINES["I82357"] = true

View File

@ -37,6 +37,7 @@ aha1542a_device::aha1542a_device(const machine_config &mconfig, const char *tag,
aha1542b_device::aha1542b_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: aha154x_device(mconfig, AHA1542B, tag, owner, clock)
, m_busaic(*this, "busaic")
{
}
@ -44,13 +45,21 @@ void aha154x_device::device_start()
{
}
void aha154x_device::i8085_map(address_map &map)
void aha1542a_device::i8085_map(address_map &map)
{
map(0x0000, 0x3fff).rom().region("mcode", 0);
map(0x8000, 0x800f).m("scsi:7:scsic", FUNC(aic6250_device::map));
map(0xe000, 0xe7ff).ram();
}
void aha1542b_device::i8085_map(address_map &map)
{
map(0x0000, 0x3fff).rom().region("mcode", 0);
map(0x8000, 0x800f).m("scsi:7:scsic", FUNC(aic6250_device::map));
map(0xa000, 0xa003).rw(m_busaic, FUNC(aic565_device::local_r), FUNC(aic565_device::local_w));
map(0xe000, 0xe7ff).ram();
}
static INPUT_PORTS_START(aha1542a)
PORT_START("SETUP")
PORT_DIPNAME(0x01, 0x01, "Synchronous Negotiation") PORT_DIPLOCATION("J1:1")
@ -338,11 +347,8 @@ void aha154x_device::scsic_config(device_t *device)
downcast<aic6250_device &>(*device).port_b_r_cb().set_ioport("^^CONFIG");
}
void aha154x_device::device_add_mconfig(machine_config &config)
void aha154x_device::scsi_add(machine_config &config)
{
i8085a_cpu_device &localcpu(I8085A(config, "localcpu", 10'000'000));
localcpu.set_addrmap(AS_PROGRAM, &aha154x_device::i8085_map);
NSCSI_BUS(config, "scsi");
NSCSI_CONNECTOR(config, "scsi:0", aha154x_scsi_devices, nullptr);
NSCSI_CONNECTOR(config, "scsi:1", aha154x_scsi_devices, nullptr);
@ -353,6 +359,28 @@ void aha154x_device::device_add_mconfig(machine_config &config)
NSCSI_CONNECTOR(config, "scsi:6", aha154x_scsi_devices, nullptr);
NSCSI_CONNECTOR(config, "scsi:7", aha154x_scsi_devices, "scsic", true)
.set_option_machine_config("scsic", [this] (device_t *device) { scsic_config(device); });
}
void aha1542a_device::device_add_mconfig(machine_config &config)
{
i8085a_cpu_device &localcpu(I8085A(config, "localcpu", 10'000'000));
localcpu.set_addrmap(AS_PROGRAM, &aha1542a_device::i8085_map);
scsi_add(config);
DP8473(config, m_fdc, 24_MHz_XTAL);
}
void aha1542b_device::device_add_mconfig(machine_config &config)
{
i8085a_cpu_device &localcpu(I8085A(config, "localcpu", 10'000'000));
localcpu.set_addrmap(AS_PROGRAM, &aha1542b_device::i8085_map);
AIC565(config, m_busaic);
m_busaic->hrst_callback().set_inputline("localcpu", INPUT_LINE_RESET);
// Soft reset interrupt is not used
scsi_add(config);
DP8473(config, m_fdc, 24_MHz_XTAL);
}

View File

@ -12,6 +12,7 @@
#pragma once
#include "isa.h"
#include "machine/aic565.h"
#include "machine/upd765.h"
class aha154x_device : public device_t, public device_isa16_card_interface
@ -20,9 +21,8 @@ protected:
aha154x_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
virtual void device_start() override;
virtual void device_add_mconfig(machine_config &config) override;
void i8085_map(address_map &map);
void scsi_add(machine_config &config);
void scsic_config(device_t *device);
required_device<upd765_family_device> m_fdc;
@ -39,6 +39,10 @@ public:
protected:
virtual ioport_constructor device_input_ports() const override;
virtual const tiny_rom_entry *device_rom_region() const override;
virtual void device_add_mconfig(machine_config &config) override;
private:
void i8085_map(address_map &map);
};
class aha1542b_device : public aha154x_device
@ -51,6 +55,12 @@ public:
protected:
virtual ioport_constructor device_input_ports() const override;
virtual const tiny_rom_entry *device_rom_region() const override;
virtual void device_add_mconfig(machine_config &config) override;
private:
void i8085_map(address_map &map);
required_device<aic565_device> m_busaic;
};
DECLARE_DEVICE_TYPE(AHA1542A, aha1542a_device)

View File

@ -46,6 +46,7 @@ aha174x_device::aha174x_device(const machine_config &mconfig, device_type type,
: device_t(mconfig, type, tag, owner, clock)
, device_isa16_card_interface(mconfig, *this)
, m_hpc(*this, "hpc")
, m_busaic(*this, "busaic")
, m_bios(*this, "bios")
{
}
@ -68,6 +69,7 @@ void aha174x_device::device_start()
void aha174x_device::hpc_map(address_map &map)
{
map(0x2000, 0x2003).rw(m_busaic, FUNC(aic565_device::local_r), FUNC(aic565_device::local_w));
map(0x4000, 0x4002).rw("bmic", FUNC(i82355_device::local_r), FUNC(i82355_device::local_w));
map(0x5000, 0x500f).m("scsi:7:scsic", FUNC(aic6251a_device::map));
map(0x8000, 0xffff).rom().region("mcode", 0);
@ -108,7 +110,12 @@ void aha1742a_device::device_add_mconfig(machine_config &config)
HPC46003(config, m_hpc, 40_MHz_XTAL / 2);
m_hpc->set_addrmap(AS_PROGRAM, &aha1742a_device::hpc_map);
AIC565(config, m_busaic);
m_busaic->hrst_callback().set_inputline(m_hpc, INPUT_LINE_RESET);
//m_busaic->srst_callback().set_inputline(m_hpc, hpc_device::EI_LINE);
I82355(config, "bmic", 0);
//bmic.lint_callback().set_inputline(m_hpc, hpc_device::I2_LINE);
NSCSI_BUS(config, "scsi");
NSCSI_CONNECTOR(config, "scsi:0", aha174x_scsi_devices, nullptr);

View File

@ -13,6 +13,7 @@
#include "isa.h"
#include "cpu/hpc/hpc.h"
#include "machine/aic565.h"
#include "machine/upd765.h"
class aha174x_device : public device_t, public device_isa16_card_interface
@ -26,6 +27,7 @@ protected:
void scsic_config(device_t *device);
required_device<hpc46003_device> m_hpc;
required_device<aic565_device> m_busaic;
required_region_ptr<u8> m_bios;
};

View File

@ -0,0 +1,271 @@
// license:BSD-3-Clause
// copyright-holders:AJR
/**********************************************************************
Adaptec AIC-565 Bus Auxiliary Interface Chip
This ASIC implements the standard mailbox interface for Adaptec's
ISA SCSI host adapters. It provides no specific SCSI functions,
however, and most of the status register bits are defined by
firmware implementation and have no special I/O features.
The local processor interface is an enhanced version of that which
the AHA-1542A provides using generic logic chips.
**********************************************************************/
#include "emu.h"
#include "aic565.h"
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
// device type definition
DEFINE_DEVICE_TYPE(AIC565, aic565_device, "aic565", "AIC-565 Bus Auxiliary Interface Chip")
//**************************************************************************
// DEVICE IMPLEMENTATION
//**************************************************************************
//-------------------------------------------------
// aic565_device - constructor
//-------------------------------------------------
aic565_device::aic565_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, AIC565, tag, owner, clock)
, m_hrst_callback(*this)
, m_srst_callback(*this)
, m_irq_callback(*this)
, m_data_to_host(0)
, m_data_from_host(0)
, m_local_status(0)
, m_aux_status(0)
, m_interrupt_flags(0)
{
}
//-------------------------------------------------
// device_resolve_objects - resolve objects that
// may be needed for other devices to set
// initial conditions at start time
//-------------------------------------------------
void aic565_device::device_resolve_objects()
{
// resolve callbacks
m_hrst_callback.resolve_safe();
m_srst_callback.resolve_safe();
m_irq_callback.resolve_safe();
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void aic565_device::device_start()
{
// register state
save_item(NAME(m_data_to_host));
save_item(NAME(m_data_from_host));
save_item(NAME(m_local_status));
save_item(NAME(m_aux_status));
save_item(NAME(m_interrupt_flags));
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void aic565_device::device_reset()
{
m_local_status = 0;
m_aux_status = 0;
m_interrupt_flags = 0;
m_hrst_callback(CLEAR_LINE);
m_srst_callback(CLEAR_LINE);
m_irq_callback(CLEAR_LINE);
}
//-------------------------------------------------
// host_r - read one byte from a host register
//-------------------------------------------------
u8 aic565_device::host_r(offs_t offset)
{
switch (offset & 0x03)
{
case 0:
// Bit 2 = data in port full
// Bit 3 = command/data out port full
return (m_local_status & 0xf1) | (m_aux_status & 0x80) >> 5 | (m_aux_status & 0x04) << 1;
case 1:
// Data in port is no longer full
if (!machine().side_effects_disabled())
m_aux_status &= 0x7f;
return m_data_to_host;
case 2:
return m_interrupt_flags;
default:
if (!machine().side_effects_disabled())
logerror("Host read from undocumented register %d\n", offset);
return 0;
}
}
//-------------------------------------------------
// host_w - write one byte to a host register
//-------------------------------------------------
void aic565_device::host_w(offs_t offset, u8 data)
{
machine().scheduler().synchronize(timer_expired_delegate(FUNC(aic565_device::host_sync_w), this), (offset & 3) << 8 | data);
}
//-------------------------------------------------
// host_sync_w - synchronization callback for
// host register writes
//-------------------------------------------------
TIMER_CALLBACK_MEMBER(aic565_device::host_sync_w)
{
const offs_t offset = param >> 8;
const u8 data = param & 0xff;
switch (offset)
{
case 0:
if (BIT(data, 7))
{
// Hard reset (self-clearing)
m_hrst_callback(ASSERT_LINE);
m_hrst_callback(CLEAR_LINE);
}
if (BIT(data, 6))
{
// Soft reset (may cause interrupt on local processor)
m_aux_status |= 0x10;
m_srst_callback(ASSERT_LINE);
}
if (BIT(data, 5))
{
// Host interrupt reset
m_aux_status &= 0xfe;
m_interrupt_flags = 0;
m_irq_callback(CLEAR_LINE);
}
if (BIT(data, 4))
{
// SCSI bus reset
m_aux_status |= 0x08;
}
break;
case 1:
// Fill the command/data out port
m_data_from_host = data;
m_aux_status |= 0x04;
break;
default:
logerror("Host write to undocumented register %d = %02X\n", offset, data);
break;
}
}
//-------------------------------------------------
// local_r - read one byte from a local register
//-------------------------------------------------
u8 aic565_device::local_r(offs_t offset)
{
// Local read register 3 is the auxiliary status register
// Local read register 2 seems to be an undocumented mirror of this
if (BIT(offset, 1))
return m_aux_status;
else if (BIT(offset, 0))
{
// Command/data out port is no longer full
if (!machine().side_effects_disabled())
m_aux_status &= 0xfb;
return m_data_from_host;
}
else
return m_interrupt_flags; // also not documented (bits 3 and 0 tested)
}
//-------------------------------------------------
// local_w - write one byte to a local register
//-------------------------------------------------
void aic565_device::local_w(offs_t offset, u8 data)
{
machine().scheduler().synchronize(timer_expired_delegate(FUNC(aic565_device::local_sync_w), this), (offset & 3) << 8 | data);
}
//-------------------------------------------------
// local_sync_w - synchronization callback for
// local writes
//-------------------------------------------------
TIMER_CALLBACK_MEMBER(aic565_device::local_sync_w)
{
const offs_t offset = param >> 8;
const u8 data = param & 0xff;
switch (offset)
{
case 0:
// Set the local status
m_local_status = data;
break;
case 1:
// Fill the data in port
m_data_to_host = data;
m_aux_status |= 0x80;
break;
case 2:
// Bit 7 = host interrupt active
if (BIT(m_interrupt_flags, 7) != BIT(data, 7))
{
if (BIT(data, 7))
{
m_aux_status |= 0x01;
m_irq_callback(ASSERT_LINE);
}
else
{
m_aux_status &= 0xfe;
m_irq_callback(CLEAR_LINE);
}
}
// Other bits of this register are firmware-defined
m_interrupt_flags = data;
break;
case 3:
// Clear reset (data is irrelevant)
if (BIT(m_aux_status, 4))
m_srst_callback(CLEAR_LINE);
m_aux_status &= 0xe7;
break;
}
}

View File

@ -0,0 +1,66 @@
// license:BSD-3-Clause
// copyright-holders:AJR
/**********************************************************************
Adaptec AIC-565 Bus Auxiliary Interface Chip
**********************************************************************/
#ifndef MAME_MACHINE_AIC565_H
#define MAME_MACHINE_AIC565_H 1
#pragma once
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
// ======================> aic565_device
class aic565_device : public device_t
{
public:
// construction/destruction
aic565_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
// callback configuration
auto hrst_callback() { return m_hrst_callback.bind(); }
auto srst_callback() { return m_srst_callback.bind(); }
auto irq_callback() { return m_irq_callback.bind(); }
// host register access
u8 host_r(offs_t offset);
void host_w(offs_t offset, u8 data);
// local CPU access
u8 local_r(offs_t offset);
void local_w(offs_t offset, u8 data);
protected:
// device-level overrides
virtual void device_resolve_objects() override;
virtual void device_start() override;
virtual void device_reset() override;
private:
// synchronization helpers
TIMER_CALLBACK_MEMBER(host_sync_w);
TIMER_CALLBACK_MEMBER(local_sync_w);
// callback objects
devcb_write_line m_hrst_callback;
devcb_write_line m_srst_callback;
devcb_write_line m_irq_callback;
// internal state
uint8_t m_data_to_host;
uint8_t m_data_from_host;
uint8_t m_local_status;
uint8_t m_aux_status;
uint8_t m_interrupt_flags;
};
// device type declaration
DECLARE_DEVICE_TYPE(AIC565, aic565_device)
#endif // MAME_MACHINE_AIC565_H