hp9k_3xx: add HP98265A SCSI controller (nw)

This commit is contained in:
Sven Schnelle 2018-10-09 20:11:24 +02:00
parent c918cf267a
commit c0a6d6bf23
5 changed files with 386 additions and 1 deletions

View File

@ -883,6 +883,8 @@ if (BUSES["HPDIO"]~=null) then
files {
MAME_DIR .. "src/devices/bus/hp_dio/hp_dio.cpp",
MAME_DIR .. "src/devices/bus/hp_dio/hp_dio.h",
MAME_DIR .. "src/devices/bus/hp_dio/hp98265a.cpp",
MAME_DIR .. "src/devices/bus/hp_dio/hp98265a.h",
MAME_DIR .. "src/devices/bus/hp_dio/hp98543.cpp",
MAME_DIR .. "src/devices/bus/hp_dio/hp98543.h",
MAME_DIR .. "src/devices/bus/hp_dio/hp98544.cpp",

View File

@ -0,0 +1,308 @@
// license:BSD-3-Clause
// copyright-holders:Sven Schnelle
/***************************************************************************
HP98265A SCSI interface
***************************************************************************/
#include "emu.h"
#define VERBOSE 0
#include "logmacro.h"
#include "hp98265a.h"
#include "machine/nscsi_bus.h"
#include "machine/nscsi_cd.h"
#include "machine/nscsi_hd.h"
#include "machine/mb87030.h"
DEFINE_DEVICE_TYPE_NS(HPDIO_98265A, bus::hp_dio, dio16_98265a_device, "hp98265a", "HP98265A SCSI S16 Interface")
namespace bus {
namespace hp_dio {
static void scsi_devices(device_slot_interface &device)
{
device.option_add("cdrom", NSCSI_CDROM);
device.option_add("harddisk", NSCSI_HARDDISK);
}
void dio16_98265a_device::mb87030_scsi_adapter(device_t *device)
{
mb87030_device &spc = downcast<mb87030_device &>(*device);
spc.set_clock(8_MHz_XTAL);
spc.out_irq_callback().set("^^", FUNC(dio16_98265a_device::irq_w));
spc.out_dreq_callback().set("^^", FUNC(dio16_98265a_device::dmar0_w));
}
void dio16_98265a_device::device_add_mconfig(machine_config &config)
{
NSCSI_BUS(config, m_scsibus, 0);
nscsi_connector &scsicon0(NSCSI_CONNECTOR(config, "scsibus:0", 0));
scsi_devices(scsicon0);
scsicon0.set_default_option("harddisk");
scsi_devices(NSCSI_CONNECTOR(config, "scsibus:1", 0));
scsi_devices(NSCSI_CONNECTOR(config, "scsibus:2", 0));
scsi_devices(NSCSI_CONNECTOR(config, "scsibus:3", 0));
scsi_devices(NSCSI_CONNECTOR(config, "scsibus:4", 0));
nscsi_connector &scsicon6(NSCSI_CONNECTOR(config, "scsibus:5", 0));
scsi_devices(scsicon6);
scsicon6.set_default_option("cdrom");
scsi_devices(NSCSI_CONNECTOR(config, "scsibus:6", 0));
nscsi_connector &scsicon7(NSCSI_CONNECTOR(config, "scsibus:7", 0));
scsicon7.option_add_internal("mb87030", MB87030);
scsicon7.set_default_option("mb87030");
scsicon7.set_fixed(true);
scsicon7.set_option_machine_config("mb87030", mb87030_scsi_adapter);
}
dio16_98265a_device::dio16_98265a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
dio16_98265a_device(mconfig, HPDIO_98265A, tag, owner, clock)
{
}
dio16_98265a_device::dio16_98265a_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_dio32_card_interface(mconfig, *this),
m_scsibus(*this, "scsibus"),
m_spc(*this, "scsibus:7:mb87030"),
m_sw1(*this, "SW1"),
m_sw2(*this, "SW2"),
m_irq_state(false)
{
}
constexpr int REG_SW1_INT_LEVEL_SHIFT = 0;
constexpr int REG_SW1_INT_LEVEL_MASK = 0x3;
constexpr int REG_SW1_SELECT_CODE_SHIFT = 2;
constexpr int REG_SW1_SELECT_CODE_MASK = 0x1f;
constexpr int REG_SW2_SCSI_ADDR_SHIFT = 0;
constexpr int REG_SW2_SCSI_ADDR_MASK = 0x07;
constexpr int REG_SW2_SCSI_PARITY = 0x08;
static INPUT_PORTS_START(hp98265a_port)
PORT_START("SW1")
PORT_DIPNAME(REG_SW1_INT_LEVEL_MASK << REG_SW1_INT_LEVEL_SHIFT, 0x01, "INT Level")
PORT_DIPSETTING(0 << REG_SW1_INT_LEVEL_SHIFT, "3")
PORT_DIPSETTING(1 << REG_SW1_INT_LEVEL_SHIFT, "4")
PORT_DIPSETTING(2 << REG_SW1_INT_LEVEL_SHIFT, "5")
PORT_DIPSETTING(3 << REG_SW1_INT_LEVEL_SHIFT, "6")
PORT_DIPNAME(REG_SW1_SELECT_CODE_MASK << REG_SW1_SELECT_CODE_SHIFT, 0x0e << REG_SW1_SELECT_CODE_SHIFT, "Select code")
PORT_DIPSETTING(0 << REG_SW1_SELECT_CODE_SHIFT, "0")
PORT_DIPSETTING(1 << REG_SW1_SELECT_CODE_SHIFT, "1")
PORT_DIPSETTING(2 << REG_SW1_SELECT_CODE_SHIFT, "2")
PORT_DIPSETTING(3 << REG_SW1_SELECT_CODE_SHIFT, "3")
PORT_DIPSETTING(4 << REG_SW1_SELECT_CODE_SHIFT, "4")
PORT_DIPSETTING(5 << REG_SW1_SELECT_CODE_SHIFT, "5")
PORT_DIPSETTING(6 << REG_SW1_SELECT_CODE_SHIFT, "6")
PORT_DIPSETTING(7 << REG_SW1_SELECT_CODE_SHIFT, "7")
PORT_DIPSETTING(8 << REG_SW1_SELECT_CODE_SHIFT, "8")
PORT_DIPSETTING(9 << REG_SW1_SELECT_CODE_SHIFT, "9")
PORT_DIPSETTING(10 << REG_SW1_SELECT_CODE_SHIFT, "10")
PORT_DIPSETTING(11 << REG_SW1_SELECT_CODE_SHIFT, "11")
PORT_DIPSETTING(12 << REG_SW1_SELECT_CODE_SHIFT, "12")
PORT_DIPSETTING(13 << REG_SW1_SELECT_CODE_SHIFT, "13")
PORT_DIPSETTING(14 << REG_SW1_SELECT_CODE_SHIFT, "14")
PORT_DIPSETTING(15 << REG_SW1_SELECT_CODE_SHIFT, "15")
PORT_DIPSETTING(16 << REG_SW1_SELECT_CODE_SHIFT, "16")
PORT_DIPSETTING(17 << REG_SW1_SELECT_CODE_SHIFT, "17")
PORT_DIPSETTING(18 << REG_SW1_SELECT_CODE_SHIFT, "18")
PORT_DIPSETTING(19 << REG_SW1_SELECT_CODE_SHIFT, "19")
PORT_DIPSETTING(20 << REG_SW1_SELECT_CODE_SHIFT, "20")
PORT_DIPSETTING(21 << REG_SW1_SELECT_CODE_SHIFT, "21")
PORT_DIPSETTING(22 << REG_SW1_SELECT_CODE_SHIFT, "22")
PORT_DIPSETTING(23 << REG_SW1_SELECT_CODE_SHIFT, "23")
PORT_DIPSETTING(24 << REG_SW1_SELECT_CODE_SHIFT, "24")
PORT_DIPSETTING(25 << REG_SW1_SELECT_CODE_SHIFT, "25")
PORT_DIPSETTING(26 << REG_SW1_SELECT_CODE_SHIFT, "26")
PORT_DIPSETTING(27 << REG_SW1_SELECT_CODE_SHIFT, "27")
PORT_DIPSETTING(28 << REG_SW1_SELECT_CODE_SHIFT, "28")
PORT_DIPSETTING(29 << REG_SW1_SELECT_CODE_SHIFT, "29")
PORT_DIPSETTING(30 << REG_SW1_SELECT_CODE_SHIFT, "30")
PORT_DIPSETTING(31 << REG_SW1_SELECT_CODE_SHIFT, "31")
PORT_START("SW2")
PORT_DIPNAME(REG_SW2_SCSI_ADDR_MASK << REG_SW2_SCSI_ADDR_SHIFT, 0x00, "SCSI Address")
PORT_DIPSETTING(0 << REG_SW2_SCSI_ADDR_SHIFT, "0")
PORT_DIPSETTING(1 << REG_SW2_SCSI_ADDR_SHIFT, "1")
PORT_DIPSETTING(2 << REG_SW2_SCSI_ADDR_SHIFT, "2")
PORT_DIPSETTING(3 << REG_SW2_SCSI_ADDR_SHIFT, "3")
PORT_DIPSETTING(4 << REG_SW2_SCSI_ADDR_SHIFT, "4")
PORT_DIPSETTING(5 << REG_SW2_SCSI_ADDR_SHIFT, "5")
PORT_DIPSETTING(6 << REG_SW2_SCSI_ADDR_SHIFT, "6")
PORT_DIPSETTING(7 << REG_SW2_SCSI_ADDR_SHIFT, "7")
PORT_DIPNAME(REG_SW2_SCSI_PARITY, 0x00, "SCSI Parity")
PORT_DIPSETTING(0, "Off")
PORT_DIPSETTING(REG_SW2_SCSI_PARITY, "On")
INPUT_PORTS_END
ioport_constructor dio16_98265a_device::device_input_ports() const
{
return INPUT_PORTS_NAME(hp98265a_port);
}
void dio16_98265a_device::device_start()
{
save_item(NAME(m_irq_state));
save_item(NAME(m_installed_io));
save_item(NAME(m_control));
save_item(NAME(m_dmar0));
m_installed_io = false;
}
void dio16_98265a_device::map(address_map &map)
{
}
void dio16_98265a_device::device_reset()
{
uint8_t code = m_sw1->read() >> REG_SW1_SELECT_CODE_SHIFT;
code &= REG_SW1_SELECT_CODE_MASK;
if (!m_installed_io)
{
program_space()->install_readwrite_handler(
0x600000 + (code * 0x10000),
0x6007ff + (code * 0x10000),
read16_delegate(FUNC(dio16_98265a_device::io_r), this),
write16_delegate(FUNC(dio16_98265a_device::io_w), this));
program_space()->install_device(0x6e0020, 0x6e003f, *m_spc, &mb87030_device::map, 0x00ff00ff);
m_installed_io = true;
}
m_control = 0;
m_irq_state = false;
m_spc->reset_w(true);
m_spc->reset_w(false);
}
int dio16_98265a_device::get_int_level()
{
return (m_sw1->read() >> REG_SW1_INT_LEVEL_SHIFT) &
REG_SW1_INT_LEVEL_MASK;
}
READ16_MEMBER(dio16_98265a_device::io_r)
{
uint16_t ret = 0xffff;
switch(offset) {
case 0: /* ID */
ret = 0x07;
break;
case 1:
ret = m_control | (m_irq_state ? 0x40 : 0) | (get_int_level() << 4);
break;
case 2:
ret = m_spc->data_read();
break;
case 3:
ret = 0xe8; /* Flush/Configuration register */
break;
}
LOG("io_r: offset=%02X ret=%02X\n",offset, ret);
return ret;
}
WRITE16_MEMBER(dio16_98265a_device::io_w)
{
LOG("io_w: offset=%02X, data=%02X\n", offset, data);
switch(offset) {
case 0:
device_reset();
break;
case 1:
if (data & 0x80)
update_irq(m_irq_state);
else
update_irq(false);
m_control = data & 0x8f;
update_dma();
break;
case 2:
uint8_t val = 0;
if (data & 0x80)
val |= nscsi_device::S_REQ;
if (data & 0x40)
val |= nscsi_device::S_ACK;
if (data & 0x08)
val |= nscsi_device::S_BSY;
if (data & 0x04)
val |= nscsi_device::S_MSG;
if (data & 0x02)
val |= nscsi_device::S_CTL;
if (data & 0x01)
val |= nscsi_device::S_INP;
m_spc->ctrl_write(val, nscsi_device::S_ALL);
break;
}
}
void dio16_98265a_device::update_irq(bool state)
{
int irq_level = get_int_level();
LOG("irq_w: %sassert %d\n", state ? "" : "de", irq_level+3);
irq3_out(state && irq_level == 0);
irq4_out(state && irq_level == 1);
irq5_out(state && irq_level == 2);
irq6_out(state && irq_level == 3);
}
WRITE_LINE_MEMBER(dio16_98265a_device::irq_w)
{
LOG("%s: %s\n", __FUNCTION__, state ? "true" : "false");
if ((m_control & 0x80) && m_irq_state != state)
update_irq(state);
m_irq_state = state;
}
void dio16_98265a_device::dmack_w_in(int channel, uint8_t data)
{
if(channel == 0 && !(m_control & REG_CONTROL_DE0))
return;
if(channel == 1 && !(m_control & REG_CONTROL_DE1))
return;
m_spc->dma_w(data);
}
uint8_t dio16_98265a_device::dmack_r_in(int channel)
{
if(channel == 0 && !(m_control & REG_CONTROL_DE0))
return 0xff;
if(channel == 1 && !(m_control & REG_CONTROL_DE1))
return 0xff;
return m_spc->dma_r();
}
void dio16_98265a_device::update_dma()
{
dmar0_out((m_control & REG_CONTROL_DE0) && m_dmar0);
dmar1_out((m_control & REG_CONTROL_DE1) && m_dmar0);
}
WRITE_LINE_MEMBER(dio16_98265a_device::dmar0_w)
{
m_dmar0 = state;
update_dma();
}
}
}

View File

@ -0,0 +1,72 @@
// license:BSD-3-Clause
// copyright-holders:Sven Schnelle
#ifndef MAME_BUS_HPDIO_98265A_H
#define MAME_BUS_HPDIO_98265A_H
#pragma once
#include "hp_dio.h"
#include "machine/mb87030.h"
#include "bus/scsi/scsi.h"
#include "bus/scsi/scsicd.h"
namespace bus {
namespace hp_dio {
class dio16_98265a_device :
public device_t,
public device_dio32_card_interface
{
public:
// construction/destruction
dio16_98265a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
void mb87030(device_t *device);
void map(address_map &map);
protected:
dio16_98265a_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
// 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;
DECLARE_READ16_MEMBER(io_r);
DECLARE_WRITE16_MEMBER(io_w);
void dmack_w_in(int channel, uint8_t data) override;
uint8_t dmack_r_in(int channel) override;
DECLARE_WRITE_LINE_MEMBER(dmar0_w);
DECLARE_WRITE_LINE_MEMBER(irq_w);
required_device<nscsi_bus_device> m_scsibus;
required_device<mb87030_device> m_spc;
private:
static constexpr int REG_CONTROL_DE0 = (1 << 0);
static constexpr int REG_CONTROL_DE1 = (1 << 1);
static void mb87030_scsi_adapter(device_t *device);
required_ioport m_sw1;
required_ioport m_sw2;
int get_int_level();
void update_irq(bool state);
void update_dma();
bool m_installed_io;
uint8_t m_control;
bool m_irq_state;
bool m_dmar0;
};
}
}
DECLARE_DEVICE_TYPE_NS(HPDIO_98265A, bus::hp_dio, dio16_98265a_device)
#endif // MAME_BUS_HPDIO_98265A_H

View File

@ -8,6 +8,7 @@
#include "emu.h"
#include "hp_dio.h"
#include "hp98265a.h"
#include "hp98543.h"
#include "hp98544.h"
#include "hp98603a.h"
@ -364,5 +365,6 @@ void dio16_cards(device_slot_interface & device)
void dio32_cards(device_slot_interface & device)
{
device.option_add("98265a", HPDIO_98265A);
device.option_add("98620", HPDIO_98620);
}

View File

@ -386,7 +386,8 @@ MACHINE_CONFIG_START(hp9k3xx_state::hp9k320)
DIO32_SLOT(config, "sl2", 0, "diobus", dio16_cards, "98603b", false);
DIO32_SLOT(config, "sl3", 0, "diobus", dio16_cards, "98644", false);
DIO32_SLOT(config, "sl4", 0, "diobus", dio32_cards, "98620", false);
DIO32_SLOT(config, "sl5", 0, "diobus", dio16_cards, nullptr, false);
DIO32_SLOT(config, "sl5", 0, "diobus", dio32_cards, "98265a", false);
DIO32_SLOT(config, "sl6", 0, "diobus", dio16_cards, nullptr, false);
MACHINE_CONFIG_END
MACHINE_CONFIG_START(hp9k3xx_state::hp9k330)