Merge pull request #6731 from shattered/_acefde6b82f

pdp11: qbus skeleton, pc11
This commit is contained in:
R. Belmont 2020-05-23 15:24:03 -04:00 committed by GitHub
commit 8ee9494bfe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 734 additions and 0 deletions

View File

@ -3659,6 +3659,20 @@ if (BUSES["SBUS"]~=null) then
}
end
---------------------------------------------------
--
--@src/devices/bus/qbus/qbus.h,BUSES["QBUS"] = true
---------------------------------------------------
if (BUSES["QBUS"]~=null) then
files {
MAME_DIR .. "src/devices/bus/qbus/pc11.cpp",
MAME_DIR .. "src/devices/bus/qbus/pc11.h",
MAME_DIR .. "src/devices/bus/qbus/qbus.cpp",
MAME_DIR .. "src/devices/bus/qbus/qbus.h",
}
end
---------------------------------------------------
--
--@src/devices/bus/ql/exp.h,BUSES["QL"] = true

View File

@ -873,6 +873,7 @@ BUSES["PSI_KEYBOARD"] = true
BUSES["PSX_CONTROLLER"] = true
BUSES["PSX_PARALLEL"] = true
BUSES["QL"] = true
BUSES["QBUS"] = true
BUSES["RS232"] = true
BUSES["S100"] = true
BUSES["SAT_CTRL"] = true

View File

@ -0,0 +1,230 @@
// license:BSD-3-Clause
// copyright-holders:Sergey Svishchev
/***************************************************************************
DEC PC11 paper tape reader and punch controller (punch not implemented)
***************************************************************************/
#include "pc11.h"
//#define LOG_GENERAL (1U << 0)
#define LOG_DBG (1U << 2)
//#define VERBOSE (LOG_GENERAL | LOG_DBG)
//#define LOG_OUTPUT_FUNC printf
#include "logmacro.h"
#define LOGDBG(...) LOGMASKED(LOG_DBG, __VA_ARGS__)
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
DEFINE_DEVICE_TYPE(DEC_PC11, pc11_device, "pc11", "DEC PC11 controller")
//**************************************************************************
// MACROS / CONSTANTS
//**************************************************************************
enum
{
REGISTER_RCSR = 0,
REGISTER_RBUF,
REGISTER_TCSR,
REGISTER_TBUF
};
const char* pc11_regnames[] = {
"RCSR", "RBUF", "TCSR", "TBUF"
};
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// pc11_device - constructor
//-------------------------------------------------
pc11_device::pc11_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, DEC_PC11, tag, owner, clock)
, device_image_interface(mconfig, *this)
, device_qbus_card_interface(mconfig, *this)
, m_rxvec(070)
, m_txvec(074)
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void pc11_device::device_start()
{
m_bus->install_device(0177550, 0177557, read16_delegate(*this, FUNC(pc11_device::read)),
write16_delegate(*this, FUNC(pc11_device::write)));
// resolve callbacks
// save state
save_item(NAME(m_rcsr));
save_item(NAME(m_rbuf));
save_item(NAME(m_tcsr));
save_item(NAME(m_tbuf));
// about 300 cps
emu_timer *timer = timer_alloc();
timer->adjust(attotime::from_usec(333), 0, attotime::from_usec(333));
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void pc11_device::device_reset()
{
LOG("Reset, rxvec %03o txvec %03o\n", m_rxvec, m_txvec);
m_rcsr = m_rbuf = m_tbuf = 0;
m_tcsr = CSR_DONE;
m_rxrdy = m_txrdy = CLEAR_LINE;
m_bus->birq4_w(CLEAR_LINE);
}
int pc11_device::z80daisy_irq_state()
{
if (m_rxrdy == ASSERT_LINE || m_txrdy == ASSERT_LINE)
return Z80_DAISY_INT;
else
return 0;
}
int pc11_device::z80daisy_irq_ack()
{
int vec = -1;
if (m_rxrdy == ASSERT_LINE)
{
m_rxrdy = CLEAR_LINE;
vec = m_rxvec;
}
else if (m_txrdy == ASSERT_LINE)
{
m_txrdy = CLEAR_LINE;
vec = m_txvec;
}
if (vec > 0)
LOGDBG("IRQ ACK vec %03o\n", vec);
return vec;
}
void pc11_device::z80daisy_irq_reti()
{
}
image_init_result pc11_device::call_load()
{
/* reader unit */
m_fd = this;
m_rcsr &= ~(CSR_ERR | CSR_BUSY);
LOG("call_load filename %s is_open %d\n", m_fd->filename(), m_fd->is_open());
return image_init_result::PASS;
}
void pc11_device::call_unload()
{
/* reader unit */
m_fd = nullptr;
m_rcsr |= CSR_ERR;
}
//-------------------------------------------------
// read - register read
//-------------------------------------------------
READ16_MEMBER(pc11_device::read)
{
uint16_t data = 0;
switch (offset & 0x03)
{
case REGISTER_RCSR:
data = m_rcsr & PTRCSR_IMP;
break;
case REGISTER_RBUF:
data = m_rbuf & 0377;
m_rcsr &= ~CSR_DONE;
clear_virq(m_bus->birq4_w, m_rcsr, CSR_IE, m_rxrdy);
break;
}
LOGDBG("R %06o == %06o\n", 0177550 + (offset << 1), data);
return data;
}
//-------------------------------------------------
// write - register write
//-------------------------------------------------
WRITE16_MEMBER(pc11_device::write)
{
LOGDBG("W %06o <- %06o\n", 0177550 + (offset << 1), data);
switch (offset & 0x03)
{
case REGISTER_RCSR:
if ((data & CSR_IE) == 0)
{
clear_virq(m_bus->birq4_w, 1, 1, m_rxrdy);
}
else if ((m_rcsr & (CSR_DONE + CSR_IE)) == CSR_DONE)
{
raise_virq(m_bus->birq4_w, 1, 1, m_rxrdy);
}
if (data & CSR_GO)
{
m_rcsr = (m_rcsr & ~CSR_DONE) | CSR_BUSY;
clear_virq(m_bus->birq4_w, m_rcsr, CSR_IE, m_rxrdy);
}
m_rcsr = ((m_rcsr & ~PTRCSR_WR) | (data & PTRCSR_WR));
break;
case REGISTER_RBUF:
break;
}
}
void pc11_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
uint8_t reply;
if (!(m_rcsr & CSR_BUSY))
return;
LOGDBG("Timer rcsr %06o id %d param %d m_fd %p\n", m_rcsr, id, param, m_fd);
m_rcsr = (m_rcsr | CSR_ERR) & ~CSR_BUSY;
if (m_fd && m_fd->exists() && (m_fd->fread(&reply, 1) == 1))
{
m_rcsr = (m_rcsr | CSR_DONE) & ~CSR_ERR;
m_rbuf = reply;
}
raise_virq(m_bus->birq4_w, m_rcsr, CSR_IE, m_rxrdy);
}

View File

@ -0,0 +1,92 @@
// license:BSD-3-Clause
// copyright-holders:Sergey Svishchev
/***************************************************************************
DEC PC11 paper tape reader and punch controller (punch not implemented)
***************************************************************************/
#pragma once
#ifndef __PC11__
#define __PC11__
#include "emu.h"
#include "qbus.h"
#include "includes/pdp11.h"
#include "softlist_dev.h"
#define PTRCSR_IMP (CSR_ERR + CSR_BUSY + CSR_DONE + CSR_IE)
#define PTRCSR_WR (CSR_IE)
#define PTPCSR_IMP (CSR_ERR + CSR_DONE + CSR_IE)
#define PTPCSR_WR (CSR_IE)
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
// ======================> pc11_device
class pc11_device : public device_t,
public device_image_interface,
public device_qbus_card_interface
{
public:
// construction/destruction
pc11_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// image-level overrides
virtual iodevice_t image_type() const noexcept override { return IO_PUNCHTAPE; }
virtual bool is_readable() const noexcept override { return true; }
virtual bool is_writeable() const noexcept override { return false; }
virtual bool is_creatable() const noexcept override { return false; }
virtual bool must_be_loaded() const noexcept override { return false; }
virtual bool is_reset_on_load() const noexcept override { return false; }
virtual const char *image_interface() const noexcept override { return "pdp11_ptap"; }
virtual const char *file_extensions() const noexcept override { return "bin,bim,lda"; }
virtual image_init_result call_load() override;
virtual void call_unload() override;
virtual const software_list_loader &get_software_list_loader() const override { return image_software_list_loader::instance(); }
DECLARE_READ16_MEMBER(read);
DECLARE_WRITE16_MEMBER(write);
protected:
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
// device_z80daisy_interface overrides
virtual int z80daisy_irq_state() override;
virtual int z80daisy_irq_ack() override;
virtual void z80daisy_irq_reti() override;
private:
int m_rxvec;
int m_txvec;
device_image_interface *m_fd;
line_state m_rxrdy;
line_state m_txrdy;
uint16_t m_rcsr;
uint16_t m_rbuf;
uint16_t m_tcsr;
uint16_t m_tbuf;
const char *pc11_regnames[4];
};
// device type definition
DECLARE_DEVICE_TYPE(DEC_PC11, pc11_device)
#endif

View File

@ -0,0 +1,178 @@
// license:BSD-3-Clause
// copyright-holders:Sergey Svishchev
/**********************************************************************
DEC Q-Bus emulation (skeleton)
**********************************************************************/
#include "emu.h"
// Peripheral boards
#include "pc11.h"
#include "qbus.h"
void qbus_cards(device_slot_interface &device)
{
device.option_add("pc11", DEC_PC11); /* Paper tape reader and punch */
}
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
DEFINE_DEVICE_TYPE(QBUS, qbus_device, "qbus", "QBUS bus")
DEFINE_DEVICE_TYPE(QBUS_SLOT, qbus_slot_device, "qbus_slot", "QBUS slot")
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// device_qbus_card_interface - constructor
//-------------------------------------------------
device_qbus_card_interface::device_qbus_card_interface(const machine_config &mconfig, device_t &device) :
device_interface(device, "qbus"),
m_bus(nullptr),
m_next(nullptr)
{
}
//-------------------------------------------------
// qbus_slot_device - constructor
//-------------------------------------------------
qbus_slot_device::qbus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, QBUS_SLOT, tag, owner, clock),
device_slot_interface(mconfig, *this),
m_write_birq4(*this),
m_write_birq5(*this),
m_write_birq6(*this),
m_write_birq7(*this),
m_write_bdmr(*this),
m_bus(*this, DEVICE_SELF_OWNER)
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void qbus_slot_device::device_start()
{
device_qbus_card_interface *dev = dynamic_cast<device_qbus_card_interface *>(get_card_device());
if (dev) m_bus->add_card(dev);
m_write_birq4.resolve_safe();
m_write_birq5.resolve_safe();
m_write_birq6.resolve_safe();
m_write_birq7.resolve_safe();
m_write_bdmr.resolve_safe();
}
//-------------------------------------------------
// qbus_device - constructor
//-------------------------------------------------
qbus_device::qbus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, QBUS, tag, owner, clock),
device_memory_interface(mconfig, *this),
device_z80daisy_interface(mconfig, *this),
m_program_config("QBUS A18", ENDIANNESS_BIG, 16, 16, 0, address_map_constructor()),
m_out_birq4_cb(*this),
m_out_birq5_cb(*this),
m_out_birq6_cb(*this),
m_out_birq7_cb(*this),
m_out_bdmr_cb(*this)
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void qbus_device::device_start()
{
// resolve callbacks
m_out_birq4_cb.resolve_safe();
m_out_birq5_cb.resolve_safe();
m_out_birq6_cb.resolve_safe();
m_out_birq7_cb.resolve_safe();
m_out_bdmr_cb.resolve_safe();
m_maincpu = owner()->subdevice<cpu_device>(m_cputag);
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void qbus_device::device_reset()
{
}
//-------------------------------------------------
// add_card - add card
//-------------------------------------------------
void qbus_device::add_card(device_qbus_card_interface *card)
{
card->m_bus = this;
m_device_list.append(*card);
}
void qbus_device::install_device(offs_t start, offs_t end, read16_delegate rhandler, write16_delegate whandler, uint32_t mask)
{
m_maincpu->space(AS_PROGRAM).install_readwrite_handler(start, end, rhandler, whandler, mask);
}
//-------------------------------------------------
// z80daisy_interface
//-------------------------------------------------
int qbus_device::z80daisy_irq_state()
{
int data = 0;
device_qbus_card_interface *entry = m_device_list.first();
while (entry)
{
data = entry->z80daisy_irq_state();
if (data)
return data;
entry = entry->next();
}
return data;
}
int qbus_device::z80daisy_irq_ack()
{
int vec = -1;
device_qbus_card_interface *entry = m_device_list.first();
while (entry)
{
vec = entry->z80daisy_irq_ack();
if (vec > 0)
return vec;
entry = entry->next();
}
return vec;
}
void qbus_device::z80daisy_irq_reti()
{
}

168
src/devices/bus/qbus/qbus.h Normal file
View File

@ -0,0 +1,168 @@
// license:BSD-3-Clause
// copyright-holders:Sergey Svishchev
/**********************************************************************
DEC Q-Bus emulation (skeleton)
**********************************************************************/
#ifndef MAME_BUS_QBUS_QBUS_H
#define MAME_BUS_QBUS_QBUS_H
#pragma once
#include "machine/z80daisy.h"
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
class qbus_device;
// ======================> device_qbus_card_interface
class device_qbus_card_interface : public device_interface
{
friend class qbus_device;
template <class ElementType> friend class simple_list;
public:
device_qbus_card_interface *next() const { return m_next; }
// device_qbus_card_interface overrides
virtual void biaki_w(int state) { }
virtual void bdmgi_w(int state) { }
protected:
// construction/destruction
device_qbus_card_interface(const machine_config &mconfig, device_t &device);
virtual int z80daisy_irq_state() { return 0; }
virtual int z80daisy_irq_ack() { return -1; }
virtual void z80daisy_irq_reti() { }
qbus_device *m_bus;
private:
device_qbus_card_interface *m_next;
};
// ======================> qbus_device
class qbus_device : public device_t,
public device_memory_interface,
public device_z80daisy_interface
{
public:
// construction/destruction
qbus_device(const machine_config &mconfig, const char *tag, device_t *owner, const char *cputag)
: qbus_device(mconfig, tag, owner, (uint32_t)0)
{
set_cputag(cputag);
}
qbus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
~qbus_device() { m_device_list.detach_all(); }
// inline configuration
void set_cputag(const char *tag) { m_cputag = tag; }
virtual space_config_vector memory_space_config() const override
{
return space_config_vector {
std::make_pair(AS_PROGRAM, &m_program_config)
};
}
auto birq4() { return m_out_birq4_cb.bind(); }
auto birq5() { return m_out_birq6_cb.bind(); }
auto birq6() { return m_out_birq6_cb.bind(); }
auto birq7() { return m_out_birq7_cb.bind(); }
void add_card(device_qbus_card_interface *card);
void install_device(offs_t start, offs_t end, read16_delegate rhandler, write16_delegate whandler, uint32_t mask=0xffffffff);
DECLARE_WRITE_LINE_MEMBER(birq4_w) { m_out_birq4_cb(state); }
DECLARE_WRITE_LINE_MEMBER(birq5_w) { m_out_birq5_cb(state); }
DECLARE_WRITE_LINE_MEMBER(birq6_w) { m_out_birq6_cb(state); }
DECLARE_WRITE_LINE_MEMBER(birq7_w) { m_out_birq7_cb(state); }
DECLARE_WRITE_LINE_MEMBER(bdmr_w) { m_out_bdmr_cb(state); }
const address_space_config m_program_config;
protected:
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
// device_z80daisy_interface overrides
virtual int z80daisy_irq_state() override;
virtual int z80daisy_irq_ack() override;
virtual void z80daisy_irq_reti() override;
// internal state
cpu_device *m_maincpu;
const char *m_cputag;
private:
devcb_write_line m_out_birq4_cb;
devcb_write_line m_out_birq5_cb;
devcb_write_line m_out_birq6_cb;
devcb_write_line m_out_birq7_cb;
devcb_write_line m_out_bdmr_cb;
simple_list<device_qbus_card_interface> m_device_list;
};
// ======================> qbus_slot_device
class qbus_slot_device : public device_t, public device_slot_interface
{
public:
// construction/destruction
template <typename T>
qbus_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt)
: qbus_slot_device(mconfig, tag, owner, DERIVED_CLOCK(1, 1))
{
option_reset();
opts(*this);
set_default_option(dflt);
set_fixed(false);
}
qbus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// computer interface
DECLARE_WRITE_LINE_MEMBER( biaki_w ) { if (m_card) m_card->biaki_w(state); }
DECLARE_WRITE_LINE_MEMBER( bdmgi_w ) { if (m_card) m_card->bdmgi_w(state); }
protected:
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override { if (m_card) get_card_device()->reset(); }
devcb_write_line m_write_birq4;
devcb_write_line m_write_birq5;
devcb_write_line m_write_birq6;
devcb_write_line m_write_birq7;
devcb_write_line m_write_bdmr;
device_qbus_card_interface *m_card;
private:
required_device<qbus_device> m_bus;
};
// device type definition
DECLARE_DEVICE_TYPE(QBUS, qbus_device)
DECLARE_DEVICE_TYPE(QBUS_SLOT, qbus_slot_device)
void qbus_cards(device_slot_interface &device);
#endif // MAME_BUS_QBUS_QBUS_H

View File

@ -89,6 +89,7 @@
****************************************************************************/
#include "emu.h"
#include "bus/qbus/qbus.h"
#include "cpu/t11/t11.h"
#include "cpu/i86/i186.h"
#include "machine/terminal.h"
@ -102,6 +103,7 @@ public:
: driver_device(mconfig, type, tag)
, m_maincpu(*this, "maincpu")
, m_terminal(*this, "terminal")
, m_qbus(*this, "qbus")
{ }
void pdp11ub2(machine_config &config);
@ -112,6 +114,7 @@ public:
private:
required_device<t11_device> m_maincpu;
required_device<generic_terminal_device> m_terminal;
required_device<qbus_device> m_qbus;
DECLARE_READ16_MEMBER( teletype_ctrl_r );
DECLARE_WRITE16_MEMBER( teletype_ctrl_w );
void kbd_put(u8 data);
@ -378,6 +381,13 @@ void pdp11_state::pdp11(machine_config &config)
m_terminal->set_keyboard_callback(FUNC(pdp11_state::kbd_put));
RX01(config, "rx01", 0);
QBUS(config, m_qbus, 0);
m_qbus->set_cputag("maincpu");
m_qbus->birq4().set_inputline(m_maincpu, T11_IRQ0);
QBUS_SLOT(config, "qbus" ":1", qbus_cards, "pc11");
QBUS_SLOT(config, "qbus" ":2", qbus_cards, nullptr);
QBUS_SLOT(config, "qbus" ":3", qbus_cards, nullptr);
QBUS_SLOT(config, "qbus" ":4", qbus_cards, nullptr);
}
void pdp11_state::pdp11ub2(machine_config &config)

41
src/mame/includes/pdp11.h Normal file
View File

@ -0,0 +1,41 @@
// license:GPL-2.0+
// copyright-holders:SIMH project
/*****************************************************************************
*
* includes/pdp11.h
*
****************************************************************************/
#ifndef PDP11_H_
#define PDP11_H_
/*
* taken from PDP11/pdp11_defs.h in SIMH
*/
/* Device CSRs */
#define CSR_V_GO 0 /* go */
#define CSR_V_IE 6 /* interrupt enable */
#define CSR_V_DONE 7 /* done */
#define CSR_V_BUSY 11 /* busy */
#define CSR_V_ERR 15 /* error */
#define CSR_GO (1u << CSR_V_GO)
#define CSR_IE (1u << CSR_V_IE)
#define CSR_DONE (1u << CSR_V_DONE)
#define CSR_BUSY (1u << CSR_V_BUSY)
#define CSR_ERR (1u << CSR_V_ERR)
#define clear_virq(_callback, _csr, _ie, _intrq) \
if ((_csr) & (_ie)) { (_intrq) = CLEAR_LINE; }
#define raise_virq(_callback, _csr, _ie, _intrq) \
if ((_csr) & (_ie)) { (_intrq) = ASSERT_LINE; _callback (ASSERT_LINE); }
#define UPDATE_16BIT(_storage, _data, _mask) \
do { *_storage = ((*_storage & ~_mask) | (_data & _mask)); } while (0)
#endif /* PDP11_H_ */