diff options
Diffstat (limited to 'src/devices/bus/ieee488/hp9122c.cpp')
-rw-r--r-- | src/devices/bus/ieee488/hp9122c.cpp | 383 |
1 files changed, 383 insertions, 0 deletions
diff --git a/src/devices/bus/ieee488/hp9122c.cpp b/src/devices/bus/ieee488/hp9122c.cpp new file mode 100644 index 00000000000..94c52a7512f --- /dev/null +++ b/src/devices/bus/ieee488/hp9122c.cpp @@ -0,0 +1,383 @@ +// license:BSD-3-Clause +// copyright-holders: Sven Schnelle +/********************************************************************* + + hp9122c.cpp + + HP9122c dual floppy disk drive + +*********************************************************************/ + +#include "emu.h" +#include "hp9122c.h" +#include "cpu/m6809/m6809.h" +#include "machine/i8291a.h" +#include "machine/wd_fdc.h" + +DEFINE_DEVICE_TYPE(HP9122C, hp9122c_device, "hp9122c", "HP9122C Dual High density disk drive") + +hp9122c_device::hp9122c_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t{mconfig, HP9122C, tag, owner, clock}, + device_ieee488_interface{mconfig, *this}, + m_cpu{*this , "cpu"}, + m_i8291a{*this, "i8291a"}, + m_fdc{*this, "mb8876"}, + m_floppy{*this, "floppy%u", 0}, + m_hpib_addr{*this , "ADDRESS"}, + m_testmode{*this, "TESTMODE"}, + m_intsel{3}, + m_fdc_irq{false}, + m_i8291a_irq{false}, + m_fdc_drq{false}, + m_i8291a_drq{false}, + m_cpuirq{false}, + m_cpufirq{false}, + m_index_int{false}, + m_ds0{false}, + m_ds1{false} +{ +} + +static INPUT_PORTS_START(hp9122c_port) + PORT_START("ADDRESS") + PORT_CONFNAME(0x1f, 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(7, "8") + PORT_CONFSETTING(7, "9") + PORT_CONFSETTING(7, "10") + PORT_CONFSETTING(7, "11") + PORT_CONFSETTING(7, "12") + PORT_CONFSETTING(7, "13") + PORT_CONFSETTING(7, "14") + PORT_CONFSETTING(7, "15") + + PORT_START("TESTMODE") + PORT_CONFNAME(0x01, 0x00, "Testmode") + PORT_CONFSETTING(0, DEF_STR(Off)) + PORT_CONFSETTING(1, DEF_STR(On)) + +INPUT_PORTS_END + +ioport_constructor hp9122c_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(hp9122c_port); +} + +void hp9122c_device::device_start() +{ + for (auto &floppy : m_floppy) + floppy->get_device()->setup_index_pulse_cb(floppy_image_device::index_pulse_cb(&hp9122c_device::index_pulse_cb, this)); + + save_item(NAME(m_intsel)); + save_item(NAME(m_fdc_irq)); + save_item(NAME(m_fdc_drq)); + save_item(NAME(m_i8291a_irq)); + save_item(NAME(m_i8291a_drq)); + save_item(NAME(m_cpuirq)); + save_item(NAME(m_cpufirq)); + save_item(NAME(m_index_int)); + save_item(NAME(m_ds0)); + save_item(NAME(m_ds1)); +} + +void hp9122c_device::device_reset() +{ + m_fdc_irq = false; + m_fdc_drq = false; + m_i8291a_irq = false; + m_i8291a_drq = false; + m_cpuirq = false; + m_cpufirq = false; + m_ds0 = false; + m_ds1 = false; + m_index_int = false; +} + +void hp9122c_device::ieee488_eoi(int state) +{ + m_i8291a->eoi_w(state); +} + +void hp9122c_device::ieee488_dav(int state) +{ + m_i8291a->dav_w(state); +} + +void hp9122c_device::ieee488_nrfd(int state) +{ + m_i8291a->nrfd_w(state); +} + +void hp9122c_device::ieee488_ndac(int state) +{ + m_i8291a->ndac_w(state); +} + +void hp9122c_device::ieee488_ifc(int state) +{ + m_i8291a->ifc_w(state); +} + +void hp9122c_device::ieee488_srq(int state) +{ + m_i8291a->srq_w(state); +} + +void hp9122c_device::ieee488_atn(int state) +{ + m_i8291a->atn_w(state); +} + +void hp9122c_device::ieee488_ren(int state) +{ + m_i8291a->ren_w(state); +} + +WRITE_LINE_MEMBER(hp9122c_device::i8291a_eoi_w) +{ + m_bus->eoi_w(this, state); +} + +WRITE_LINE_MEMBER(hp9122c_device::i8291a_dav_w) +{ + m_bus->dav_w(this, state); +} + +WRITE_LINE_MEMBER(hp9122c_device::i8291a_nrfd_w) +{ + m_bus->nrfd_w(this, state); +} + +WRITE_LINE_MEMBER(hp9122c_device::i8291a_ndac_w) +{ + m_bus->ndac_w(this, state); +} + +WRITE_LINE_MEMBER(hp9122c_device::i8291a_ifc_w) +{ + m_bus->ifc_w(this, state); +} + +WRITE_LINE_MEMBER(hp9122c_device::i8291a_srq_w) +{ + m_bus->srq_w(this, state); +} + +WRITE_LINE_MEMBER(hp9122c_device::i8291a_atn_w) +{ + m_bus->atn_w(this, state); +} + +WRITE_LINE_MEMBER(hp9122c_device::i8291a_ren_w) +{ + m_bus->ren_w(this, state); +} + +WRITE_LINE_MEMBER(hp9122c_device::i8291a_int_w) +{ + m_i8291a_irq = state; + update_intsel(); +} + +WRITE_LINE_MEMBER(hp9122c_device::i8291a_dreq_w) +{ + m_i8291a_drq = state; + update_intsel(); +} + +WRITE_LINE_MEMBER(hp9122c_device::fdc_intrq_w) +{ + m_fdc_irq = state; + update_intsel(); +} + +WRITE_LINE_MEMBER(hp9122c_device::fdc_drq_w) +{ + m_fdc_drq = state; + update_intsel(); +} + +void hp9122c_device::update_intsel() +{ + bool irq = false, firq = false; + + switch (m_intsel & 3) { + case 0: + /* fdc int connected */ + irq = m_fdc_drq; + firq = m_fdc_irq; + break; + case 1: + /* i8291a ints connected */ + irq = m_i8291a_drq; + firq = m_i8291a_irq; + break; + case 2: + irq = m_index_int; + firq = false; + break; + + case 3: + irq = false; + firq = false; + break; + } + + if (m_cpufirq != firq) + m_cpu->set_input_line(M6809_FIRQ_LINE, firq ? ASSERT_LINE : CLEAR_LINE); + + if (m_cpuirq != irq) + m_cpu->set_input_line(M6809_IRQ_LINE, irq ? ASSERT_LINE : CLEAR_LINE); + + m_cpuirq = irq; + m_cpufirq = firq; +} + +READ8_MEMBER(hp9122c_device::i8291a_dio_r) +{ + return m_bus->read_dio(); +} + +WRITE8_MEMBER(hp9122c_device::i8291a_dio_w) +{ + m_bus->dio_w(this, data); +} + +READ8_MEMBER(hp9122c_device::status_r) +{ + uint8_t ret = REG_STATUS_DUAL|REG_STATUS_DISKCHG; + auto addr = m_hpib_addr->read(); + + if (!m_testmode->read()) + ret |= 0x10; + + ret |= ((addr & 0x08) << 3) | (addr & 0x07); + + floppy_image_device *floppy = nullptr; + if (m_ds0) + floppy = m_floppy[0]->get_device(); + if (m_ds1) + floppy = m_floppy[1]->get_device(); + + if (floppy) { + auto variant = floppy->get_variant(); + if (variant == floppy_image::DSDD || variant == floppy_image::SSDD) + ret |= REG_STATUS_LOW_DENSITY; + } + + return ret; +} + +WRITE8_MEMBER(hp9122c_device::cmd_w) +{ + floppy_image_device *floppy0 = m_floppy[0]->get_device(); + floppy_image_device *floppy1 = m_floppy[1]->get_device(); + + m_ds0 = !(data & REG_CNTL_DS0) && floppy0; + m_ds1 = !(data & REG_CNTL_DS1) && floppy1; + + if (m_ds0) { + floppy0->mon_w(0); + floppy0->ss_w(!(data & REG_CNTL_HEADSEL)); + m_fdc->set_floppy(floppy0); + } else if (m_ds1) { + floppy1->mon_w(0); + floppy1->ss_w(!(data & REG_CNTL_HEADSEL)); + m_fdc->set_floppy(floppy1); + } + + if (data & REG_CNTL_CLOCK_SEL) + m_fdc->set_clock(XTAL(8'000'000)/4); + else + m_fdc->set_clock(XTAL(8'000'000)/8); + + m_intsel = ((data & REG_CNTL_INTSEL0) >> 7) | ((data & REG_CNTL_INTSEL1) >> 2); + update_intsel(); +} + +void hp9122c_device::index_pulse_cb(floppy_image_device *floppy, int state) +{ + m_fdc->index_callback(floppy, state); + + if (state) + m_index_int = true; + update_intsel(); + +} + +WRITE8_MEMBER(hp9122c_device::clridx_w) +{ + m_index_int = false; + update_intsel(); +} + +ROM_START(hp9122c) + ROM_REGION(0x4000 , "cpu" , 0) + ROM_LOAD("09122-15515.bin" , 0x0000, 0x4000 , CRC(d385e488) SHA1(93b2015037d76cc68b6252df03d6f184104605b9)) +ROM_END + +static void hp9122c_floppies(device_slot_interface &device) +{ + device.option_add("35dd" , FLOPPY_35_DD); + device.option_add("35hd" , FLOPPY_35_HD); +} + +static const floppy_format_type hp9122c_floppy_formats[] = { + FLOPPY_MFI_FORMAT, + FLOPPY_TD0_FORMAT, + nullptr +}; + +const tiny_rom_entry *hp9122c_device::device_rom_region() const +{ + return ROM_NAME(hp9122c); +} + +void hp9122c_device::cpu_map(address_map &map) +{ + map(0x0000, 0x0800).ram(); + map(0x2000, 0x2003).rw(m_fdc, FUNC(mb8876_device::read), FUNC(mb8876_device::write)).mirror(0x1ff4); + map(0x4000, 0x4007).m("i8291a", FUNC(i8291a_device::map)).mirror(0x1ff8); + map(0x6000, 0x7fff).rw(FUNC(hp9122c_device::status_r), FUNC(hp9122c_device::cmd_w)); + map(0x8000, 0x8001).w(FUNC(hp9122c_device::clridx_w)); + map(0xc000, 0xffff).rom().region("cpu", 0); +} + +MACHINE_CONFIG_START(hp9122c_device::device_add_mconfig) + MCFG_DEVICE_ADD("cpu" , MC6809 , XTAL(8'000'000)) + MCFG_DEVICE_PROGRAM_MAP(cpu_map) + + // without this flag, 'DMA' transfer via SYNC instruction + // will not work + MCFG_QUANTUM_PERFECT_CPU("cpu") + + MCFG_DEVICE_ADD("mb8876", MB8876, 8_MHz_XTAL / 4) + MCFG_WD_FDC_INTRQ_CALLBACK(WRITELINE(*this, hp9122c_device, fdc_intrq_w)) + MCFG_WD_FDC_DRQ_CALLBACK(WRITELINE(*this,hp9122c_device, fdc_drq_w)) + + MCFG_DEVICE_ADD("i8291a", I8291A, XTAL(2'000'000)) + + MCFG_I8291A_EOI_WRITE_CB(WRITELINE(*this, hp9122c_device, i8291a_eoi_w)) + MCFG_I8291A_DAV_WRITE_CB(WRITELINE(*this, hp9122c_device, i8291a_dav_w)) + MCFG_I8291A_NRFD_WRITE_CB(WRITELINE(*this, hp9122c_device, i8291a_nrfd_w)) + MCFG_I8291A_NDAC_WRITE_CB(WRITELINE(*this, hp9122c_device, i8291a_ndac_w)) + MCFG_I8291A_SRQ_WRITE_CB(WRITELINE(*this, hp9122c_device, i8291a_srq_w)) + MCFG_I8291A_DIO_WRITE_CB(WRITE8(*this, hp9122c_device, i8291a_dio_w)) + MCFG_I8291A_DIO_READ_CB(READ8(*this, hp9122c_device, i8291a_dio_r)) + MCFG_I8291A_INT_WRITE_CB(WRITELINE(*this, hp9122c_device, i8291a_int_w)) + MCFG_I8291A_DREQ_WRITE_CB(WRITELINE(*this, hp9122c_device, i8291a_dreq_w)) + + MCFG_FLOPPY_DRIVE_ADD("floppy0" , hp9122c_floppies , "35hd" , hp9122c_floppy_formats) + MCFG_FLOPPY_DRIVE_SOUND(true) + MCFG_SLOT_FIXED(true) + MCFG_FLOPPY_DRIVE_ADD("floppy1" , hp9122c_floppies , "35hd" , hp9122c_floppy_formats) + MCFG_FLOPPY_DRIVE_SOUND(true) + MCFG_SLOT_FIXED(true) +MACHINE_CONFIG_END |