bus/ieee488: Added HP9133 Floppy/Fixed disk drive. (#12561)

* machine/wd2010.cpp: Increased maximum sectors per track to 32.
* machine/wd2010.cpp: Implemented multi-sector transfers.
* machine/wd2010.cpp: Don't change current cylinder on reset.
* cpu/m6809: Added sync acknowledge callback.
* hp/hp98x6.cpp: Added HP9133 slot option.
This commit is contained in:
Sven Schnelle 2024-07-18 00:00:18 +02:00 committed by GitHub
parent 2695a185f9
commit ba5952efab
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 950 additions and 13 deletions

View File

@ -1582,6 +1582,8 @@ if (BUSES["IEEE488"]~=null) then
MAME_DIR .. "src/devices/bus/ieee488/shark.h",
MAME_DIR .. "src/devices/bus/ieee488/hp9122c.cpp",
MAME_DIR .. "src/devices/bus/ieee488/hp9122c.h",
MAME_DIR .. "src/devices/bus/ieee488/hp9133.cpp",
MAME_DIR .. "src/devices/bus/ieee488/hp9133.h",
MAME_DIR .. "src/devices/bus/ieee488/hp9895.cpp",
MAME_DIR .. "src/devices/bus/ieee488/hp9895.h",
MAME_DIR .. "src/devices/bus/ieee488/remote488.cpp",

View File

@ -0,0 +1,879 @@
// license:BSD-3-Clause
// copyright-holders: Sven Schnelle
/*********************************************************************
hp9133.cpp
HP9133 hard disk/floppy drive
*********************************************************************/
#include "emu.h"
#include "hp9133.h"
#include "ieee488.h"
#include "cpu/m6809/m6809.h"
#include "machine/i8291a.h"
#include "machine/wd2010.h"
#include "machine/wd_fdc.h"
#include "imagedev/floppy.h"
#include "imagedev/harddriv.h"
#include <algorithm>
//#define VERBOSE 1
#include "logmacro.h"
namespace {
class hp9133_device : public device_t,
public device_ieee488_interface
{
public:
// construction/destruction
hp9133_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
// device_t implementation
virtual void device_start() override;
virtual void device_reset() override;
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;
// device_ieee488_interface implementation
virtual void ieee488_eoi(int state) override;
virtual void ieee488_dav(int state) override;
virtual void ieee488_nrfd(int state) override;
virtual void ieee488_ndac(int state) override;
virtual void ieee488_ifc(int state) override;
virtual void ieee488_srq(int state) override;
virtual void ieee488_atn(int state) override;
virtual void ieee488_ren(int state) override;
private:
static constexpr int IO1_R_BCS_N = 0x10;
static constexpr int IO1_R_BDRQ = 0x20;
static constexpr int IO1_R_HDINT = 0x40;
static constexpr int IO1_R_HDIND = 0x80;
static constexpr int IO2_R_FDCINT = 0x10;
static constexpr int IO2_R_FDKDCH_N = 0x20;
static constexpr int IO2_R_WRTFLTERR = 0x80;
static constexpr int IO3_R_FASTDON = 0x20;
static constexpr int IO3_R_SELTST = 0x40;
static constexpr int IO3_R_TEST = 0x80;
static constexpr int IO1_W_FLT_N = 0x01;
static constexpr int IO1_W_DS1 = 0x02;
static constexpr int IO1_W_BRDY = 0x40;
static constexpr int IO1_W_WDRESET_N = 0x80;
static constexpr int IO2_W_FDCRES_N = 0x01;
static constexpr int IO2_W_CLRIND_N = 0x04;
static constexpr int IO2_W_DKCHRES_N = 0x08;
static constexpr int IO2_W_FDHDLD_N = 0x10;
static constexpr int IO2_W_FDMOTON_N = 0x20;
static constexpr int IO2_W_FDHDSEL_N = 0x40;
static constexpr int IO3_W_INTSEL_MASK = 0x03;
static constexpr int IO3_W_INTENBL_N = 0x04;
static constexpr int IO3_W_FAST = 0x10;
static constexpr int IO3_W_DMAR_W_N = 0x20;
static constexpr int IO3_W_HPB_FDC_N = 0x40;
static constexpr int IO3_W_DMA = 0x80;
required_device<mc6809_device> m_cpu;
required_device<i8291a_device> m_gpib;
required_device<wd2010_device> m_hdc;
required_device<harddisk_image_device> m_harddisk;
required_device<wd2793_device> m_fdc;
required_device<floppy_connector> m_floppy;
required_ioport m_hpib_addr;
required_ioport m_selftest;
required_ioport m_selftesten;
required_ioport m_volcfg;
required_ioport m_model;
TIMER_CALLBACK_MEMBER(floppy_motor_timeout);
TIMER_CALLBACK_MEMBER(index_timer);
TIMER_CALLBACK_MEMBER(fast_timer);
void i8291a_eoi_w(int state);
void i8291a_dav_w(int state);
void i8291a_nrfd_w(int state);
void i8291a_ndac_w(int state);
void i8291a_ifc_w(int state);
void i8291a_srq_w(int state);
void i8291a_atn_w(int state);
void i8291a_ren_w(int state);
void i8291a_dio_w(uint8_t data);
void i8291a_int_w(int state);
void i8291a_drq_w(int state);
void fdc_intrq_w(int state);
void fdc_drq_w(int state);
void hdc_reg_w(offs_t offset, uint8_t data);
uint8_t hdc_reg_r(offs_t offset);
uint8_t i8291a_dio_r();
void io1_w(uint8_t data);
void io2_w(uint8_t data);
void io3_w(uint8_t data);
uint8_t io1_r();
uint8_t io2_r();
uint8_t io3_r();
void dma_ram_w(uint8_t data);
uint8_t dma_ram_r(offs_t offset);
void cpu_map(address_map &map);
void floppy_index_cb(floppy_image_device *floppy, int state);
void hdc_bcs_cb(int state);
void hdc_bcr_cb(int state);
void hdc_bdrq_cb(int state);
void hdc_intrq_cb(int state);
void hdc_wg_cb(int state);
void hdc_readwrite_sector(bool write);
void update_intsel();
void cpu_sync_ack(int state);
emu_timer *m_motor_timer;
emu_timer *m_index_timer;
emu_timer *m_fast_timer;
uint8_t m_dma_ram[2048];
int m_dma_addr;
int m_intsel;
int m_head;
bool m_harddisk_index;
bool m_floppy_index_int;
bool m_intenable;
bool m_dmaenable;
bool m_dmaack_switch;
bool m_dma_rwn;
bool m_gpib_irq;
bool m_gpib_drq;
bool m_fdc_irq;
bool m_fdc_drq;
bool m_cpuirq;
bool m_cpufirq;
bool m_hdc_intrq;
bool m_hdc_bdrq;
bool m_hdc_bcs;
bool m_hdc_wg;
bool m_fast;
uint16_t m_hdc_cylinder;
uint8_t m_hdc_sdh;
uint8_t m_hdc_sector_count;
uint8_t m_hdc_sector_number;
uint8_t m_hdc_cmd;
};
hp9133_device::hp9133_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t{mconfig, HP9133, tag, owner, clock},
device_ieee488_interface{mconfig, *this},
m_cpu{*this, "cpu"},
m_gpib{*this, "i8291a"},
m_hdc{*this, "wd2010"},
m_harddisk{*this, "harddisk"},
m_fdc{*this, "wd2793"},
m_floppy{*this, "floppy0"},
m_hpib_addr{*this, "ADDRESS"},
m_selftest{*this, "SELFTEST"},
m_selftesten{*this, "SELFTESTEN"},
m_volcfg{*this, "VOLCFG"},
m_model{*this, "MODEL"}
{
}
static INPUT_PORTS_START(hp9133_port)
PORT_START("ADDRESS")
PORT_CONFNAME(0xf, 0x00, "HPIB address")
PORT_CONFSETTING(0, "0")
PORT_CONFSETTING(1, "1")
PORT_CONFSETTING(2, "2")
PORT_CONFSETTING(3, "3")
PORT_CONFSETTING(4, "4")
PORT_CONFSETTING(5, "5")
PORT_CONFSETTING(6, "6")
PORT_CONFSETTING(7, "7")
PORT_CONFSETTING(8, "8")
PORT_CONFSETTING(9, "9")
PORT_CONFSETTING(10, "10")
PORT_CONFSETTING(11, "11")
PORT_CONFSETTING(12, "12")
PORT_CONFSETTING(13, "13")
PORT_CONFSETTING(14, "14")
PORT_CONFSETTING(15, "15")
PORT_START("SELFTESTEN")
PORT_CONFNAME(0x1, 0x00, "Selftest Enable")
PORT_CONFSETTING(0x0, DEF_STR(Off))
PORT_CONFSETTING(0x1, DEF_STR(On))
PORT_START("SELFTEST")
PORT_CONFNAME(0xf, 0x00, "Selftest")
PORT_CONFSETTING(0x0, "RAM")
PORT_CONFSETTING(0x1, "ROM checksum")
PORT_CONFSETTING(0x2, "GPIB")
PORT_CONFSETTING(0x3, "FDC Chip")
PORT_CONFSETTING(0x4, "Floppy Seek")
PORT_CONFSETTING(0x5, "Winchester Seek")
PORT_CONFSETTING(0x6, "Floppy Speed")
PORT_CONFSETTING(0x7, "Winchester Speed")
PORT_CONFSETTING(0x8, "Floppy Write Verify")
PORT_CONFSETTING(0x9, "Winchester Write Verify")
PORT_CONFSETTING(0xa, "Floppy Verify")
PORT_CONFSETTING(0xb, "Winchester Verify")
PORT_CONFSETTING(0xc, "Floppy format")
PORT_CONFSETTING(0xd, "HDC Check")
PORT_CONFSETTING(0xe, "WD1100 Check")
PORT_CONFSETTING(0xf, "WD1100 Buffer RAM")
PORT_START("VOLCFG")
PORT_CONFNAME(0x0f, 0x00, "Volume config")
PORT_CONFSETTING(0, "0")
PORT_CONFSETTING(1, "1")
PORT_CONFSETTING(2, "2")
PORT_CONFSETTING(3, "3")
PORT_CONFSETTING(4, "4")
PORT_CONFSETTING(5, "5")
PORT_CONFSETTING(6, "6")
PORT_CONFSETTING(7, "7")
PORT_CONFSETTING(8, "8")
PORT_CONFSETTING(9, "9")
PORT_START("MODEL")
PORT_CONFNAME(0x03, 0x00, "Disc Model")
PORT_CONFSETTING(0x0, "9133D")
PORT_CONFSETTING(0x1, "9133L")
PORT_CONFSETTING(0x2, "9133H")
INPUT_PORTS_END
ioport_constructor hp9133_device::device_input_ports() const
{
return INPUT_PORTS_NAME(hp9133_port);
}
TIMER_CALLBACK_MEMBER(hp9133_device::floppy_motor_timeout)
{
auto *floppy = m_floppy->get_device();
floppy->mon_w(1);
}
void hp9133_device::device_start()
{
save_item(NAME(m_dma_ram));
save_item(NAME(m_dma_addr));
save_item(NAME(m_head));
save_item(NAME(m_intsel));
save_item(NAME(m_harddisk_index));
save_item(NAME(m_floppy_index_int));
save_item(NAME(m_intenable));
save_item(NAME(m_dmaenable));
save_item(NAME(m_dmaack_switch));
save_item(NAME(m_dma_rwn));
save_item(NAME(m_gpib_irq));
save_item(NAME(m_gpib_drq));
save_item(NAME(m_fdc_irq));
save_item(NAME(m_fdc_drq));
save_item(NAME(m_cpuirq));
save_item(NAME(m_cpufirq));
save_item(NAME(m_hdc_intrq));
save_item(NAME(m_hdc_bdrq));
save_item(NAME(m_hdc_bcs));
save_item(NAME(m_hdc_wg));
save_item(NAME(m_fast));
save_item(NAME(m_hdc_cylinder));
save_item(NAME(m_hdc_sdh));
save_item(NAME(m_hdc_sector_count));
save_item(NAME(m_hdc_sector_number));
save_item(NAME(m_hdc_cmd));
// HP firmware tests whether ECC errors are detected. MAME's WD2010
// doesn't emulate ECC so patch the ROM to ignore the ECC test result.
uint8_t *rom = memregion("cpu")->base();
rom[0x279e] = 0x12;
rom[0x279f] = 0x12;
// disable ROM checksum
rom[0x36ea] = 0x20;
m_motor_timer = timer_alloc(FUNC(hp9133_device::floppy_motor_timeout), this);
m_index_timer = timer_alloc(FUNC(hp9133_device::index_timer), this);
m_index_timer->adjust(attotime::from_hz(3600 / 60));
m_fast_timer = timer_alloc(FUNC(hp9133_device::fast_timer), this);
auto *floppy = m_floppy->get_device();
floppy->setup_index_pulse_cb(floppy_image_device::index_pulse_cb(&hp9133_device::floppy_index_cb, this));
}
void hp9133_device::device_reset()
{
std::fill(std::begin(m_dma_ram), std::end(m_dma_ram), 0);
m_dma_addr = 0;
m_intsel = 0;
m_head = 0;
m_harddisk_index = false;
m_floppy_index_int = false;
m_intenable = false;
m_dmaenable = false;
m_dmaack_switch = false;
m_dma_rwn = false;
m_gpib_irq = false;
m_gpib_drq = false;
m_fdc_irq = false;
m_fdc_drq = false;
m_cpuirq = false;
m_cpufirq = false;
m_hdc_intrq = false;
m_hdc_bdrq = false;
m_hdc_bcs = false;
m_hdc_wg = false;
m_fast = false;
m_fdc->set_floppy(m_floppy->get_device());
}
void hp9133_device::ieee488_eoi(int state)
{
m_gpib->eoi_w(state);
}
void hp9133_device::ieee488_dav(int state)
{
m_gpib->dav_w(state);
}
void hp9133_device::ieee488_nrfd(int state)
{
m_gpib->nrfd_w(state);
}
void hp9133_device::ieee488_ndac(int state)
{
m_gpib->ndac_w(state);
}
void hp9133_device::ieee488_srq(int state)
{
m_gpib->srq_w(state);
}
void hp9133_device::ieee488_ifc(int state)
{
m_gpib->ifc_w(state);
}
void hp9133_device::ieee488_atn(int state)
{
m_gpib->atn_w(state);
}
void hp9133_device::ieee488_ren(int state)
{
m_gpib->ren_w(state);
}
void hp9133_device::i8291a_eoi_w(int state)
{
m_bus->eoi_w(this, state);
}
void hp9133_device::i8291a_dav_w(int state)
{
m_bus->dav_w(this, state);
}
void hp9133_device::i8291a_nrfd_w(int state)
{
m_bus->nrfd_w(this, state);
}
void hp9133_device::i8291a_ndac_w(int state)
{
m_bus->ndac_w(this, state);
}
void hp9133_device::i8291a_srq_w(int state)
{
m_bus->srq_w(this, state);
}
void hp9133_device::i8291a_int_w(int state)
{
LOG("%s: %d\n", __func__, state);
m_gpib_irq = state;
update_intsel();
}
uint8_t hp9133_device::i8291a_dio_r()
{
uint8_t ret = m_bus->dio_r();
LOG("%s: %02x\n", __func__, (uint8_t)~ret);
return ret;
}
void hp9133_device::i8291a_dio_w(uint8_t data)
{
m_bus->dio_w(this, data);
}
void hp9133_device::i8291a_drq_w(int state)
{
LOG("%s: %d\n", __func__, state);
m_gpib_drq = state;
update_intsel();
}
TIMER_CALLBACK_MEMBER(hp9133_device::index_timer)
{
attotime next = attotime::from_hz(3600 / 60);
m_harddisk_index ^= true;
if (!m_harddisk_index)
next /= 10;
else
next -= next / 10;
m_index_timer->adjust(next);
}
void hp9133_device::cpu_sync_ack(int state)
{
LOG("%s: %d: enabled %d\n", __func__, state, m_dmaenable);
if (!m_dmaenable)
return;
if (state) {
if (m_gpib_drq)
m_cpu->set_input_line(M6809_IRQ_LINE, ASSERT_LINE);
} else {
uint8_t data;
if (!m_dma_rwn) {
data = dma_ram_r(0);
m_gpib->dout_w(data);
} else {
data = m_gpib->din_r();
dma_ram_w(data);
}
m_cpu->set_input_line(M6809_IRQ_LINE, CLEAR_LINE);
LOG("%s: sync data: %02x\n", __func__, data);
if (m_dma_addr > 256) {
LOG("DMA: all bytes transferred\n");
m_dmaenable = false;
}
}
}
void hp9133_device::update_intsel()
{
bool irq = false, firq = false;
// IRQ Multiplexing:
// +--------+----------+-----------+-------------------+---------+
// | INTSEL | 0 | 1 | 2 | 3 |
// +--------+----------+-+---------+-------------------+---------+
// | IRQ# | GPIBDREQ | GND | DMASYNC | FDCDREQ |
// | FIRQ# | GPIBINT | INDEXINT | FDCINT || GPIBINT | FDCINT |
// +--------+---------+-----------+-------------------+----------+
switch (m_intsel) {
case 0:
irq = m_gpib_drq;
firq = m_gpib_irq;
break;
case 1:
irq = false;
firq = m_floppy_index_int;
break;
case 2:
irq = (m_dmaenable && m_gpib_drq);
firq = m_fdc_irq || m_gpib_irq;
break;
case 3:
irq = m_fdc_drq;
firq = m_fdc_irq;
break;
}
if (!m_intenable) {
irq = false;
firq = false;
}
if (m_cpuirq != irq) {
m_cpu->set_input_line(M6809_IRQ_LINE, irq ? ASSERT_LINE : CLEAR_LINE);
m_cpuirq = irq;
}
if (m_cpufirq != firq) {
m_cpu->set_input_line(M6809_FIRQ_LINE, firq ? ASSERT_LINE : CLEAR_LINE);
m_cpufirq = firq;
}
}
TIMER_CALLBACK_MEMBER(hp9133_device::fast_timer)
{
if (!m_fast)
return;
if (m_gpib_drq) {
if (!m_dma_rwn)
m_gpib->dout_w(dma_ram_r(0));
else
dma_ram_w(m_gpib->din_r());
}
m_fast_timer->adjust(attotime::from_usec(50));
}
void hp9133_device::io1_w(uint8_t data)
{
// 7 - HDC Rst#
// 6 - HDC BRDY
// 5 - HD Precomp#
// 4 - HD Head 2
// 3 - HD Head 1
// 2 - HD Head 0
// 1 - Active LED
// 0 - Fault LED#
m_head = (data >> 2) & 7;
LOG("%s: %02x Head %d %s%s%s%s\n", __func__,
data, m_head,
(data & IO1_W_BRDY) ? "BRDY " : "",
(data & IO1_W_WDRESET_N) ? "" : "HDCRESET ",
(data & IO1_W_DS1) ? "ACTIVE " : "",
(data & IO1_W_FLT_N) ? "" : "FAULT ");
if (!(data & IO1_W_WDRESET_N))
m_hdc->reset();
m_hdc->buffer_ready(data & IO1_W_BRDY);
}
void hp9133_device::io2_w(uint8_t data)
{
auto *floppy = m_floppy->get_device();
// 7 - HDRecMode
// 6 - FlopHLO#?
// 5 - FlopMotor#
// 4 - FlopSide#
// 3 - Floppy Disk change reset
// 2 - ClrIdxInt
// 1
// 0 - FDCRst#
LOG("%s: %02x\n", __func__, data);
if (!(data & IO2_W_CLRIND_N))
m_floppy_index_int = false;
if (data & IO2_W_FDMOTON_N) {
m_motor_timer->adjust(attotime::from_msec(2000));
} else {
m_motor_timer->reset();
floppy->mon_w(0);
}
if (!(data & IO2_W_DKCHRES_N))
m_floppy->get_device()->dskchg_w(false);
m_floppy->get_device()->ss_w((data & IO2_W_FDHDSEL_N) ? 0 : 1);
if (!(data & IO2_W_FDCRES_N))
m_fdc->reset();
}
void hp9133_device::io3_w(uint8_t data)
{
// 7 - DMA enable
// 6 - 1 GPIPACK, 0 FDCACK
// 5 - Write Precomp?
// 4 - FAST enable?
// 3 -
// 2 - Interrupt Enable
// 0:1 - Interrupt select
m_dmaenable = data & IO3_W_DMA;
m_dmaack_switch = data & IO3_W_HPB_FDC_N;
m_dma_rwn = data & IO3_W_DMAR_W_N;
m_intenable = !(data & IO3_W_INTENBL_N);
m_fast = data & IO3_W_FAST;
m_intsel = data & IO3_W_INTSEL_MASK;
LOG("%s: %02x = INTSEL %d, INT %d DMA %d DMA start %d DMA ACK %s\n", __func__,
data, m_intsel, m_intenable, m_dmaenable, BIT(data, 4),
m_dmaack_switch ? "GPIB" : "FDC");
update_intsel();
if (m_fast)
m_fast_timer->adjust(attotime::from_usec(1000));
else
m_fast_timer->adjust(attotime::never);
}
uint8_t hp9133_device::io1_r()
{
uint8_t ret;
// 7 - hdindex
// 6 - HDC int
// 5 - HDC DRQ
// 4 - HDC BCS
// 3 - 0 Ident
ret = m_model->read() ^ 0xf;
if (m_harddisk_index)
ret |= IO1_R_HDIND;
if (m_hdc_intrq)
ret |= IO1_R_HDINT;
if (m_hdc_bdrq)
ret |= IO1_R_BDRQ;
if (m_hdc_bcs)
ret |= IO1_R_BCS_N;
if (!machine().side_effects_disabled())
LOG("%s: %02x\n", __func__, ret);
return ret;
}
uint8_t hp9133_device::io2_r()
{
uint8_t ret = 0;
// 7 - Write Fault Latch
// 5 - FlopDC#
// 4 - FDC interrupt
// 3 - 0 GPIB Address
if (m_selftesten->read()) {
ret = (m_selftest->read() & 7) ^ 0xf;
} else {
ret = m_hpib_addr->read() ^ 0xf;
}
if (m_fdc_irq)
ret |= IO2_R_FDCINT;
if (!m_floppy->get_device()->dskchg_r())
ret |= IO2_R_FDKDCH_N;
if (!machine().side_effects_disabled())
LOG("%s: %02x\n", __func__, ret);
return ret;
}
uint8_t hp9133_device::io3_r()
{
uint8_t ret = 0;
// 7 - self test enable
// 6 - self test MSB
// 5 - FASTDON
// 3-0 Volume switch
ret = m_volcfg->read() ^ 0xf;
if (!m_selftesten->read()) {
ret |= IO3_R_TEST;
} else {
if (m_selftest->read() & 8)
ret |= IO3_R_SELTST;
}
if (m_dma_addr >= 256)
ret |= IO3_R_FASTDON;
if (!machine().side_effects_disabled())
LOG("%s: %02x\n", __func__, ret);
return ret;
}
void hp9133_device::dma_ram_w(uint8_t data)
{
LOG("%s: %03x = %02x\n", __func__, m_dma_addr, data);
if (m_dma_addr < sizeof(m_dma_ram))
m_dma_ram[m_dma_addr++] = data;
}
uint8_t hp9133_device::dma_ram_r(offs_t offset)
{
if (m_dma_addr >= sizeof(m_dma_ram))
return 0;
uint8_t ret = m_dma_ram[m_dma_addr];
if (!machine().side_effects_disabled()) {
LOG("%s: %03x = %02x\n", __func__, m_dma_addr, ret);
m_dma_addr++;
}
return ret;
}
static int sdh_sector_size(uint8_t sdh)
{
constexpr int sizes[4] = { 256, 512, 1024, 128 };
return sizes[(sdh >> 5) & 3];
}
static int sdh_devsel(uint8_t sdh)
{
return (sdh >> 3) & 3;
}
void hp9133_device::hdc_readwrite_sector(bool write)
{
int sector = m_hdc->read(3);
uint32_t lba;
if (sdh_devsel(m_hdc_sdh))
return;
if (sdh_sector_size(m_hdc_sdh) != 256)
return;
if (!m_harddisk->exists())
return;
const auto &info = m_harddisk->get_info();
lba = (m_hdc_cylinder * info.heads + m_head) * info.sectors + sector;
LOG("%s: %s cyl %4d, head %d, sector %2d lba %8d\n", __func__,
write ? "WRITE" : "READ ", m_hdc_cylinder, m_head, sector, lba);
if (write) {
m_harddisk->write(lba, m_dma_ram);
} else {
m_harddisk->read(lba, m_dma_ram);
m_dma_addr = 256;
}
}
void hp9133_device::fdc_intrq_w(int state)
{
m_fdc_irq = state;
update_intsel();
}
void hp9133_device::fdc_drq_w(int state)
{
m_fdc_drq = state;
update_intsel();
}
void hp9133_device::floppy_index_cb(floppy_image_device *floppy, int state)
{
m_fdc->index_callback(floppy, state);
if (state)
m_floppy_index_int = true;
update_intsel();
}
void hp9133_device::hdc_bcs_cb(int state)
{
m_hdc_bcs = state;
}
void hp9133_device::hdc_bcr_cb(int state)
{
m_dma_addr = 0;
}
void hp9133_device::hdc_bdrq_cb(int state)
{
bool is_read = m_hdc_cmd >> 4 == 2;
m_hdc_bdrq = state;
if (state && is_read)
hdc_readwrite_sector(false);
}
void hp9133_device::hdc_wg_cb(int state)
{
bool is_write = (m_hdc_cmd >> 4) == 3;
m_hdc_wg = state;
if (state && is_write)
hdc_readwrite_sector(true);
}
void hp9133_device::hdc_intrq_cb(int state)
{
m_hdc_intrq = state;
update_intsel();
}
uint8_t hp9133_device::hdc_reg_r(offs_t offset)
{
return m_hdc->read(offset);
}
void hp9133_device::hdc_reg_w(offs_t offset, uint8_t data)
{
switch (offset) {
case 2:
m_hdc_sector_count = data;
break;
case 3:
m_hdc_sector_number = data;
break;
case 4:
m_hdc_cylinder &= ~0xff;
m_hdc_cylinder |= data;
break;
case 5:
m_hdc_cylinder &= ~0xff00;
m_hdc_cylinder |= data << 8;
break;
case 6:
m_hdc_sdh = data;
break;
case 7:
m_hdc_cmd = data;
break;
}
m_hdc->write(offset, data);
}
void hp9133_device::cpu_map(address_map &map)
{
map(0x0000, 0x0007).m(m_gpib, FUNC(i8291a_device::map));
map(0x0008, 0x000b).rw(m_fdc, FUNC(wd2793_device::read), FUNC(wd2793_device::write));
map(0x0010, 0x0017).rw(FUNC(hp9133_device::hdc_reg_r), FUNC(hp9133_device::hdc_reg_w));
map(0x0020, 0x0027).rw(FUNC(hp9133_device::dma_ram_r), FUNC(hp9133_device::dma_ram_w));
map(0x0028, 0x002f).lw8(NAME([this] (u8 data) { LOG("clear ram addr\n"); m_dma_addr = 0; }));
map(0x003f, 0x003f).nopw();
map(0x0040, 0x0040).rw(FUNC(hp9133_device::io1_r), FUNC(hp9133_device::io1_w)).mirror(0x3f3f);
map(0x0080, 0x0080).rw(FUNC(hp9133_device::io2_r), FUNC(hp9133_device::io2_w)).mirror(0x3f3f);
map(0x00c0, 0x00c0).rw(FUNC(hp9133_device::io3_r), FUNC(hp9133_device::io3_w)).mirror(0x3f3f);
map(0x4000, 0x47ff).ram().mirror(0x3800);
map(0x8000, 0xffff).rom().region("cpu", 0);
}
static void hp9133_floppies(device_slot_interface &device)
{
device.option_add("d32w", SONY_OA_D32W);
}
void hp9133_device::device_add_mconfig(machine_config &config)
{
MC6809(config, m_cpu, XTAL(8'000'000));
m_cpu->set_addrmap(AS_PROGRAM, &hp9133_device::cpu_map);
m_cpu->sync_acknowledge_write().set(FUNC(hp9133_device::cpu_sync_ack));
I8291A(config, m_gpib, XTAL(8'000'000));
m_gpib->eoi_write().set(FUNC(hp9133_device::i8291a_eoi_w));
m_gpib->dav_write().set(FUNC(hp9133_device::i8291a_dav_w));
m_gpib->nrfd_write().set(FUNC(hp9133_device::i8291a_nrfd_w));
m_gpib->ndac_write().set(FUNC(hp9133_device::i8291a_ndac_w));
m_gpib->srq_write().set(FUNC(hp9133_device::i8291a_srq_w));
m_gpib->dio_write().set(FUNC(hp9133_device::i8291a_dio_w));
m_gpib->dio_read().set(FUNC(hp9133_device::i8291a_dio_r));
m_gpib->int_write().set(FUNC(hp9133_device::i8291a_int_w));
m_gpib->dreq_write().set(FUNC(hp9133_device::i8291a_drq_w));
WD2010(config, m_hdc, XTAL(5'000'000));
m_hdc->in_sc_callback().set_constant(1);
m_hdc->in_drdy_callback().set_constant(1);
m_hdc->out_bcs_callback().set(FUNC(hp9133_device::hdc_bcs_cb));
m_hdc->out_bcr_callback().set(FUNC(hp9133_device::hdc_bcr_cb));
m_hdc->out_bdrq_callback().set(FUNC(hp9133_device::hdc_bdrq_cb));
m_hdc->out_intrq_callback().set(FUNC(hp9133_device::hdc_intrq_cb));
m_hdc->out_wg_callback().set(FUNC(hp9133_device::hdc_wg_cb));
HARDDISK(config, m_harddisk);
WD2793(config, m_fdc, XTAL(2'000'000));
m_fdc->intrq_wr_callback().set(FUNC(hp9133_device::fdc_intrq_w));
m_fdc->drq_wr_callback().set(FUNC(hp9133_device::fdc_drq_w));
FLOPPY_CONNECTOR(config, "floppy0", hp9133_floppies, "d32w",
floppy_image_device::default_mfm_floppy_formats, true).enable_sound(true);
}
ROM_START(hp9133)
ROM_REGION(0x8000, "cpu", 0)
ROM_LOAD("09133-89110_9133.bin", 0x0000, 0x4000, CRC(d7ff6b3e) SHA1(aeeae063fa43c3b163ba5c176f31df6ec1b73d0d))
ROM_LOAD("09133-89210_9133.bin", 0x4000, 0x4000, CRC(08f825e2) SHA1(61766b1f64473c17f01cbc97bd817f6076827d6a))
ROM_END
const tiny_rom_entry *hp9133_device::device_rom_region() const
{
return ROM_NAME(hp9133);
}
} // anonymous namespace
DEFINE_DEVICE_TYPE_PRIVATE(HP9133, device_ieee488_interface, hp9133_device, "hp9133", "HP9133 Floppy/Fixed disk drive")

View File

@ -0,0 +1,18 @@
// license:BSD-3-Clause
// copyright-holders: Sven Schnelle
/*********************************************************************
hp9133.h
HP9133 Fixed disk drive
*********************************************************************/
#ifndef MAME_BUS_IEEE488_HP9133_H
#define MAME_BUS_IEEE488_HP9133_H
#pragma once
DECLARE_DEVICE_TYPE(HP9133, device_ieee488_interface)
#endif // MAME_BUS_IEEE488_HP9133_H

View File

@ -421,11 +421,13 @@ void cbm_ieee488_devices(device_slot_interface &device)
// slot devices
#include "hp9122c.h"
#include "hp9133.h"
#include "hp9895.h"
void hp_ieee488_devices(device_slot_interface &device)
{
device.option_add("hp9122c", HP9122C);
device.option_add("hp9133", HP9133);
device.option_add("hp9895", HP9895);
}

View File

@ -442,6 +442,7 @@ SYNC:
// is disabled, execution continues with the next instruction.
@dummy_read_opcode_arg(0);
m_syncack_write_func(1);
while(!m_nmi_asserted && !m_firq_line && !m_irq_line)
{
// massaging the PC this way makes the debugger's behavior more
@ -453,6 +454,7 @@ SYNC:
// unmassage...
m_pc.w++;
}
m_syncack_write_func(0);
@eat(1);
return;

View File

@ -145,6 +145,7 @@ DEFINE_DEVICE_TYPE(M6809, m6809_device, "m6809", "MC6809 (legacy)")
m6809_base_device::m6809_base_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, const device_type type, int divider) :
cpu_device(mconfig, type, tag, owner, clock),
m_lic_func(*this),
m_syncack_write_func(*this),
m_program_config("program", ENDIANNESS_BIG, 8, 16),
m_sprogram_config("decrypted_opcodes", ENDIANNESS_BIG, 8, 16),
m_clock_divider(divider)

View File

@ -26,6 +26,8 @@ DECLARE_DEVICE_TYPE(M6809, m6809_device)
// Used by core CPU interface
class m6809_base_device : public cpu_device
{
public:
auto sync_acknowledge_write() { return m_syncack_write_func.bind(); }
protected:
// construction/destruction
m6809_base_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, const device_type type, int divider);
@ -171,10 +173,11 @@ protected:
bool m_lds_encountered;
int m_icount;
int m_addressing_mode;
PAIR16 m_ea; // effective address
PAIR16 m_ea; // effective address
// Callbacks
devcb_write_line m_lic_func; // LIC pin on the 6809E
devcb_write_line m_lic_func; // LIC pin on the 6809E
devcb_write_line m_syncack_write_func; // Indicates sync acknowledge buscycle
// eat cycles
inline void eat(int cycles) { m_icount -= cycles; }

View File

@ -38,7 +38,7 @@ UNIMPLEMENTED FEATURES :
#include "emu.h"
#include "wd2010.h"
#define VERBOSE 1
//#define VERBOSE 1
#include "logmacro.h"
#include <cmath>
@ -57,7 +57,8 @@ UNIMPLEMENTED FEATURES :
// #define CYLINDER_HIGH_MASK 0x03
// --------------------------------------------------------
#define MAX_MFM_SECTORS 17 // STANDARD MFM SECTORS/TRACK
// Maximum sector number before ID not found is returned.
#define MAX_MFM_SECTORS 32
// --------------------------------------------------------
// Typical access times for MFM drives (as listed in ST412_OEM Manual_Apr82)
@ -187,6 +188,8 @@ void wd2010_device::device_start()
m_complete_write_timer = timer_alloc(FUNC(wd2010_device::complete_write), this);
m_deassert_write_timer = timer_alloc(FUNC(wd2010_device::deassert_write), this);
m_deassert_read_timer = timer_alloc(FUNC(wd2010_device::deassert_read), this);
m_next_sector_timer = timer_alloc(FUNC(wd2010_device::next_sector), this);
m_present_cylinder = 0; // start somewhere
}
@ -199,8 +202,6 @@ void wd2010_device::device_reset()
m_out_intrq_cb(CLEAR_LINE);
buffer_ready(false);
m_present_cylinder = 0; // start somewhere
}
@ -231,10 +232,10 @@ uint8_t wd2010_device::read(offs_t offset)
if (offset == TASK_FILE_SDH_REGISTER)
{
logerror("(READ) %s WD2010 SDH: %u\n", machine().describe_context(), data);
logerror("(READ) %s WD2010 Head: %u\n", machine().describe_context(), HEAD);
logerror("(READ) %s WD2010 Drive: %u\n", machine().describe_context(), DRIVE);
logerror("(READ) %s WD2010 Sector Size: %u\n", machine().describe_context(), SECTOR_SIZE);
LOG("(READ) %s WD2010 SDH: %u\n", machine().describe_context(), data);
LOG("(READ) %s WD2010 Head: %u\n", machine().describe_context(), HEAD);
LOG("(READ) %s WD2010 Drive: %u\n", machine().describe_context(), DRIVE);
LOG("(READ) %s WD2010 Sector Size: %u\n", machine().describe_context(), SECTOR_SIZE);
}
break;
@ -582,9 +583,7 @@ void wd2010_device::read_sector(uint8_t data)
// FLAG "M" SET? (MULTIPLE SECTOR TRANSFERS)
if (data & 4)
logerror("WD2010 (READ): MULTIPLE SECTOR READ (M = 1).\n");
// Assume: NO "M" (MULTIPLE SECTOR TRANSFERS)
LOG("WD2010 (READ): MULTIPLE SECTOR READ (M = 1).\n");
m_out_bcs_cb(0); // deactivate BCS (!)
@ -906,6 +905,23 @@ TIMER_CALLBACK_MEMBER(wd2010_device::deassert_read)
}
}
TIMER_CALLBACK_MEMBER(wd2010_device::next_sector)
{
uint8_t cmd = m_task_file[TASK_FILE_COMMAND];
switch (cmd & 0xf0)
{
case 0x20:
read_sector(cmd);
break;
case 0x30:
write_sector(cmd);
break;
default:
break;
}
}
// Called by timer callbacks -
void wd2010_device::complete_immediate(uint8_t status)
{
@ -919,6 +935,17 @@ void wd2010_device::complete_immediate(uint8_t status)
m_out_bdrq_cb(0);
}
uint8_t cmd = m_task_file[TASK_FILE_COMMAND] & 0xf4;
if ((cmd == 0x24) || (cmd == 0x34))
{
if (--m_task_file[TASK_FILE_SECTOR_COUNT] > 1)
{
m_task_file[TASK_FILE_SECTOR_NUMBER]++;
m_next_sector_timer->adjust(attotime::from_usec(100));
return;
}
}
// Set current status (M_STATUS)
m_status = status & (255 - STATUS_DWC); // minus "unused" bit 2 (DWC)

View File

@ -54,6 +54,7 @@ protected:
TIMER_CALLBACK_MEMBER(complete_write);
TIMER_CALLBACK_MEMBER(deassert_write);
TIMER_CALLBACK_MEMBER(deassert_read);
TIMER_CALLBACK_MEMBER(next_sector);
private:
void compute_correction(uint8_t data);
@ -91,6 +92,7 @@ private:
emu_timer *m_complete_write_timer;
emu_timer *m_deassert_write_timer;
emu_timer *m_deassert_read_timer;
emu_timer *m_next_sector_timer;
void complete_write_sector(uint8_t status);
void complete_cmd(uint8_t status);

View File

@ -202,6 +202,7 @@ void hp9816_state::hp9816(machine_config &config)
ieee.atn_callback().set(m_hpib , FUNC(tms9914_device::atn_w));
ieee.ren_callback().set(m_hpib , FUNC(tms9914_device::ren_w));
IEEE488_SLOT(config, "ieee_rem", 0, remote488_devices, nullptr);
IEEE488_SLOT(config, "ieee0", 0, hp_ieee488_devices, nullptr);
INS8250(config, m_uart, UART_CLOCK);
m_uart->out_int_callback().set(FUNC(hp9816_state::uart_irq_w));