summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/msx_slot/disk.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/bus/msx_slot/disk.cpp')
-rw-r--r--src/devices/bus/msx_slot/disk.cpp813
1 files changed, 813 insertions, 0 deletions
diff --git a/src/devices/bus/msx_slot/disk.cpp b/src/devices/bus/msx_slot/disk.cpp
new file mode 100644
index 00000000000..799f05b9337
--- /dev/null
+++ b/src/devices/bus/msx_slot/disk.cpp
@@ -0,0 +1,813 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+/*
+From: erbo@xs4all.nl (erik de boer)
+
+sony and philips have used (almost) the same design
+and this is the memory layout
+but it is not a msx standard !
+
+WD1793 or wd2793 registers
+
+address
+
+7FF8H read status register
+ write command register
+7FF9H r/w track register (r/o on NMS 8245 and Sony)
+7FFAH r/w sector register (r/o on NMS 8245 and Sony)
+7FFBH r/w data register
+
+
+hardware registers
+
+address
+
+7FFCH r/w bit 0 side select
+7FFDH r/w b7>M-on , b6>in-use , b1>ds1 , b0>ds0 (all neg. logic)
+7FFEH not used
+7FFFH read b7>drq , b6>intrq
+
+set on 7FFDH bit 2 always to 0 (some use it as disk change reset)
+
+*/
+
+#include "emu.h"
+#include "disk.h"
+
+
+const device_type MSX_SLOT_DISK1 = &device_creator<msx_slot_disk1_device>;
+const device_type MSX_SLOT_DISK2 = &device_creator<msx_slot_disk2_device>;
+const device_type MSX_SLOT_DISK3 = &device_creator<msx_slot_disk3_device>;
+const device_type MSX_SLOT_DISK4 = &device_creator<msx_slot_disk4_device>;
+const device_type MSX_SLOT_DISK5 = &device_creator<msx_slot_disk5_device>;
+const device_type MSX_SLOT_DISK6 = &device_creator<msx_slot_disk6_device>;
+
+
+msx_slot_disk_device::msx_slot_disk_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source)
+ : msx_slot_rom_device(mconfig, type, name, tag, owner, clock, shortname, source)
+ , m_floppy0(NULL)
+ , m_floppy1(NULL)
+ , m_floppy2(NULL)
+ , m_floppy3(NULL)
+ , m_floppy(NULL)
+ , m_fdc_tag(NULL)
+ , m_floppy0_tag(NULL)
+ , m_floppy1_tag(NULL)
+ , m_floppy2_tag(NULL)
+ , m_floppy3_tag(NULL)
+{
+}
+
+
+void msx_slot_disk_device::device_start()
+{
+ msx_slot_rom_device::device_start();
+
+ if (m_fdc_tag == NULL)
+ {
+ fatalerror("msx_slot_disk_device: no FDC tag specified\n");
+ }
+
+ m_floppy0 = m_floppy0_tag ? owner()->subdevice<floppy_connector>(m_floppy0_tag) : NULL;
+ m_floppy1 = m_floppy1_tag ? owner()->subdevice<floppy_connector>(m_floppy1_tag) : NULL;
+ m_floppy2 = m_floppy2_tag ? owner()->subdevice<floppy_connector>(m_floppy2_tag) : NULL;
+ m_floppy3 = m_floppy3_tag ? owner()->subdevice<floppy_connector>(m_floppy3_tag) : NULL;
+
+ if (m_floppy0 == NULL && m_floppy1 == NULL)
+ {
+ logerror("msx_slot_disk_device: Warning: both floppy0 and floppy1 were not found\n");
+ }
+}
+
+
+msx_slot_wd_disk_device::msx_slot_wd_disk_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source)
+ : msx_slot_disk_device(mconfig, type, name, tag, owner, clock, shortname, source)
+ , m_fdc(NULL)
+{
+}
+
+
+void msx_slot_wd_disk_device::device_start()
+{
+ msx_slot_disk_device::device_start();
+
+ m_fdc = owner()->subdevice<wd_fdc_analog_t>(m_fdc_tag);
+
+ if (m_fdc == NULL)
+ {
+ fatalerror("msx_slot_wd_disk_device: Unable to find FDC with tag '%s'\n", m_fdc_tag);
+ }
+}
+
+
+msx_slot_tc8566_disk_device::msx_slot_tc8566_disk_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source)
+ : msx_slot_disk_device(mconfig, type, name, tag, owner, clock, shortname, source)
+ , m_fdc(NULL)
+{
+}
+
+
+void msx_slot_tc8566_disk_device::device_start()
+{
+ msx_slot_disk_device::device_start();
+
+ m_fdc = owner()->subdevice<tc8566af_device>(m_fdc_tag);
+
+ if (m_fdc == NULL)
+ {
+ fatalerror("msx_slot_tc8566_disk_device: Unable to find FDC with tag '%s'\n", m_fdc_tag);
+ }
+}
+
+
+
+msx_slot_disk1_device::msx_slot_disk1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : msx_slot_wd_disk_device(mconfig, MSX_SLOT_DISK1, "MSX Internal floppy type 1", tag, owner, clock, "msx_slot_disk1", __FILE__)
+ , m_side_control(0)
+ , m_control(0)
+{
+}
+
+
+void msx_slot_disk1_device::device_start()
+{
+ msx_slot_wd_disk_device::device_start();
+
+ save_item(NAME(m_side_control));
+ save_item(NAME(m_control));
+
+ machine().save().register_postload(save_prepost_delegate(FUNC(msx_slot_disk1_device::post_load), this));
+}
+
+
+void msx_slot_disk1_device::device_reset()
+{
+ m_fdc->dden_w(false);
+}
+
+
+void msx_slot_disk1_device::post_load()
+{
+ UINT8 data = m_control;
+
+ // To make sure the FDD busy led status gets set correctly
+ m_control ^= 0x40;
+
+ set_control(data);
+}
+
+
+void msx_slot_disk1_device::set_side_control(UINT8 data)
+{
+ m_side_control = data;
+
+ if (m_floppy)
+ {
+ m_floppy->ss_w(m_side_control & 0x01);
+ }
+}
+
+
+void msx_slot_disk1_device::set_control(UINT8 data)
+{
+ UINT8 old_m_control = m_control;
+
+ m_control = data;
+
+ switch (m_control & 0x03)
+ {
+ case 0:
+ case 2:
+ m_floppy = m_floppy0 ? m_floppy0->get_device() : NULL;
+ break;
+
+ case 1:
+ m_floppy = m_floppy1 ? m_floppy1->get_device() : NULL;
+ break;
+
+ default:
+ m_floppy = NULL;
+ break;
+ }
+
+ if (m_floppy)
+ {
+ m_floppy->mon_w((m_control & 0x80) ? 0 : 1);
+ m_floppy->ss_w(m_side_control & 0x01);
+ }
+
+ m_fdc->set_floppy(m_floppy);
+
+ if ((old_m_control ^ m_control) & 0x40)
+ {
+ set_led_status(machine(), 0, !(m_control & 0x40));
+ }
+}
+
+
+READ8_MEMBER(msx_slot_disk1_device::read)
+{
+ switch (offset)
+ {
+ case 0x7ff8:
+ case 0xbff8:
+ return m_fdc->status_r();
+
+ case 0x7ff9:
+ case 0xbff9:
+ return m_fdc->track_r();
+
+ case 0x7ffa:
+ case 0xbffa:
+ return m_fdc->sector_r();
+
+ case 0x7ffb:
+ case 0xbffb:
+ return m_fdc->data_r();
+
+ case 0x7ffc:
+ case 0xbffc:
+ return 0xfe | (m_side_control & 0x01);
+
+ case 0x7ffd:
+ case 0xbffd:
+ return ( m_control & 0x83 ) | 0x78;
+
+ case 0x7fff:
+ case 0xbfff:
+ return 0x3f | (m_fdc->intrq_r() ? 0 : 0x40) | (m_fdc->drq_r() ? 0 : 0x80);
+ }
+
+ return msx_slot_rom_device::read(space, offset);
+}
+
+
+WRITE8_MEMBER(msx_slot_disk1_device::write)
+{
+ switch (offset)
+ {
+ case 0x7ff8:
+ case 0xbff8:
+ m_fdc->cmd_w(data);
+ break;
+
+ case 0x7ff9:
+ case 0xbff9:
+ m_fdc->track_w(data);
+ break;
+
+ case 0x7ffa:
+ case 0xbffa:
+ m_fdc->sector_w(data);
+ break;
+
+ case 0x7ffb:
+ case 0xbffb:
+ m_fdc->data_w(data);
+ break;
+
+ case 0x7ffc:
+ case 0xbffc:
+ set_side_control(data);
+ break;
+
+ case 0x7ffd:
+ case 0xbffd:
+ set_control(data);
+ break;
+
+ default:
+ logerror("msx_slot_disk1_device::write: Unmapped write writing %02x to %04x\n", data, offset);
+ break;
+
+ }
+}
+
+
+msx_slot_disk2_device::msx_slot_disk2_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : msx_slot_wd_disk_device(mconfig, MSX_SLOT_DISK2, "MSX Internal floppy type 2", tag, owner, clock, "msx_slot_disk2", __FILE__)
+ , m_control(0)
+{
+}
+
+
+void msx_slot_disk2_device::device_start()
+{
+ msx_slot_wd_disk_device::device_start();
+
+ save_item(NAME(m_control));
+
+ machine().save().register_postload(save_prepost_delegate(FUNC(msx_slot_disk2_device::post_load), this));
+}
+
+
+void msx_slot_disk2_device::device_reset()
+{
+ m_fdc->dden_w(false);
+}
+
+
+void msx_slot_disk2_device::post_load()
+{
+ UINT8 data = m_control;
+
+ // To make sure the FDD busy led status gets set correctly
+ m_control ^= 0x40;
+
+ set_control(data);
+}
+
+
+void msx_slot_disk2_device::set_control(UINT8 data)
+{
+ UINT8 old_m_control = m_control;
+
+ m_control = data;
+
+ switch (m_control & 3)
+ {
+ case 1:
+ m_floppy = m_floppy0 ? m_floppy0->get_device() : NULL;
+ break;
+
+ case 2:
+ m_floppy = m_floppy1 ? m_floppy1->get_device() : NULL;
+ break;
+
+ default:
+ m_floppy = NULL;
+ break;
+ }
+
+ if (m_floppy)
+ {
+ m_floppy->mon_w((m_control & 0x08) ? 0 : 1);
+ m_floppy->ss_w((m_control & 0x04) ? 1 : 0);
+ }
+
+ m_fdc->set_floppy(m_floppy);
+
+ if ((old_m_control ^ m_control) & 0x40)
+ {
+ set_led_status(machine(), 0, !(m_control & 0x40));
+ }
+}
+
+
+READ8_MEMBER(msx_slot_disk2_device::read)
+{
+ switch (offset)
+ {
+ case 0x7fb8:
+ case 0xbfb8:
+ return m_fdc->status_r();
+
+ case 0x7fb9:
+ case 0xbfb9:
+ return m_fdc->track_r();
+
+ case 0x7fba:
+ case 0xbfba:
+ return m_fdc->sector_r();
+
+ case 0x7fbb:
+ case 0xbfbb:
+ return m_fdc->data_r();
+
+ case 0x7fbc:
+ case 0xbfbc:
+ return 0x3f | (m_fdc->drq_r() ? 0 : 0x40) | (m_fdc->intrq_r() ? 0x80 : 0);
+ }
+
+ return msx_slot_rom_device::read(space, offset);
+}
+
+
+WRITE8_MEMBER(msx_slot_disk2_device::write)
+{
+ switch (offset)
+ {
+ case 0x7fb8:
+ case 0xbfb8:
+ m_fdc->cmd_w(data);
+ break;
+
+ case 0x7fb9:
+ case 0xbfb9:
+ m_fdc->track_w(data);
+ break;
+
+ case 0x7fba:
+ case 0xbfba:
+ m_fdc->sector_w(data);
+ break;
+
+ case 0x7fbb:
+ case 0xbfbb:
+ m_fdc->data_w(data);
+ break;
+
+ case 0x7fbc:
+ case 0xbfbc:
+ set_control(data);
+ break;
+
+ default:
+ logerror("msx_slot_disk2_device::write: Unmapped write writing %02x to %04x\n", data, offset);
+ break;
+ }
+}
+
+
+
+
+
+
+msx_slot_disk3_device::msx_slot_disk3_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : msx_slot_tc8566_disk_device(mconfig, MSX_SLOT_DISK3, "MSX Internal floppy type 3", tag, owner, clock, "msx_slot_disk3", __FILE__)
+{
+}
+
+
+WRITE8_MEMBER(msx_slot_disk3_device::write)
+{
+ switch (offset)
+ {
+ case 0x7ff8: // CR0 : 0 - 0 - MEN1 - MEN0 - 0 - -FRST - 0 - DSA
+ m_fdc->dor_w(space, 2, data);
+ break;
+
+ case 0x7ff9: // CR1 : 0 - 0 - C4E - C4 - SBME - SBM - TCE - FDCTC
+ m_fdc->cr1_w(space, 3, data);
+ break;
+
+ case 0x7ffb: // Data Register
+ m_fdc->fifo_w(space, 5, data);
+ break;
+
+ default:
+ logerror("msx_slot_disk3_device::write: Unmapped write writing %02x to %04x\n", data, offset);
+ break;
+ }
+}
+
+
+READ8_MEMBER(msx_slot_disk3_device::read)
+{
+ switch (offset)
+ {
+ case 0x7ffa: // Status Register
+ return m_fdc->msr_r(space, 4);
+ case 0x7ffb: // Data Register
+ return m_fdc->fifo_r(space, 5);
+ }
+
+ return msx_slot_rom_device::read(space, offset);
+}
+
+
+
+
+
+msx_slot_disk4_device::msx_slot_disk4_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : msx_slot_tc8566_disk_device(mconfig, MSX_SLOT_DISK4, "MSX Internal floppy type 4", tag, owner, clock, "msx_slot_disk4", __FILE__)
+{
+}
+
+
+WRITE8_MEMBER(msx_slot_disk4_device::write)
+{
+ switch (offset)
+ {
+ case 0x7ff1: // FDD : x - x - MC1 - MC0 - x - x - x - x
+ break;
+
+ case 0x7ff2: // CR0 : 0 - 0 - MEN1 - MEN0 - 0 - -FRST - 0 - DSA
+ m_fdc->dor_w(space, 2, data);
+ break;
+
+ case 0x7ff3: // CR1 : 0 - 0 - C4E - C4 - SBME - SBM - TCE - FDCTC
+ m_fdc->cr1_w(space, 3, data);
+ break;
+
+ case 0x7ff5: // Data Register
+ m_fdc->fifo_w(space, 5, data);
+ break;
+
+ default:
+ logerror("msx_slot_disk4_device::write: Unmapped write writing %02x to %04x\n", data, offset);
+ break;
+ }
+}
+
+
+READ8_MEMBER(msx_slot_disk4_device::read)
+{
+ switch (offset)
+ {
+ case 0x7ff1: // FDD : x - x - MC1 - MC0 - x - x - x - x
+ logerror("msx_slot_disk4_device::write: Unmapped read from Media Change register\n");
+ break;
+
+ case 0x7ff4: // Status Register
+ return m_fdc->msr_r(space, 4);
+ case 0x7ff5: // Data Register
+ return m_fdc->fifo_r(space, 5);
+ }
+
+ return msx_slot_rom_device::read(space, offset);
+}
+
+
+
+
+msx_slot_disk5_device::msx_slot_disk5_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : msx_slot_wd_disk_device(mconfig, MSX_SLOT_DISK5, "MSX Internal floppy type 5", tag, owner, clock, "msx_slot_disk5", __FILE__)
+ , m_control(0)
+{
+}
+
+
+void msx_slot_disk5_device::device_start()
+{
+ msx_slot_wd_disk_device::device_start();
+
+ save_item(NAME(m_control));
+
+ machine().save().register_postload(save_prepost_delegate(FUNC(msx_slot_disk5_device::post_load), this));
+
+ // Install IO read/write handlers
+ address_space &space = machine().device<cpu_device>("maincpu")->space(AS_IO);
+ space.install_write_handler(0xd0, 0xd4, write8_delegate(FUNC(msx_slot_disk5_device::io_write), this));
+ space.install_read_handler(0xd0, 0xd4, read8_delegate(FUNC(msx_slot_disk5_device::io_read), this));
+}
+
+
+void msx_slot_disk5_device::device_reset()
+{
+ m_fdc->dden_w(false);
+}
+
+
+void msx_slot_disk5_device::post_load()
+{
+ set_control(m_control);
+}
+
+
+void msx_slot_disk5_device::set_control(UINT8 control)
+{
+ m_control = control;
+
+ switch (m_control & 0x0f)
+ {
+ case 0x01:
+ m_floppy = m_floppy0 ? m_floppy0->get_device() : NULL;
+ break;
+
+ case 0x02:
+ m_floppy = m_floppy1 ? m_floppy1->get_device() : NULL;
+ break;
+
+ case 0x04:
+ m_floppy = m_floppy2 ? m_floppy2->get_device() : NULL;
+ break;
+
+ case 0x08:
+ m_floppy = m_floppy3 ? m_floppy3->get_device() : NULL;
+ break;
+
+ default:
+ m_floppy = NULL;
+ break;
+ }
+
+ if (m_floppy)
+ {
+ m_floppy->mon_w((m_control & 0x20) ? 0 : 1);
+ m_floppy->ss_w((m_control & 0x10) ? 1 : 0);
+ }
+
+ m_fdc->set_floppy(m_floppy);
+}
+
+
+READ8_MEMBER(msx_slot_disk5_device::io_read)
+{
+ switch (offset)
+ {
+ case 0x00:
+ return m_fdc->status_r();
+
+ case 0x01:
+ return m_fdc->track_r();
+
+ case 0x02:
+ return m_fdc->sector_r();
+
+ case 0x03:
+ return m_fdc->data_r();
+
+ case 0x04:
+ return 0x3f | (m_fdc->drq_r() ? 0 : 0x40) | (m_fdc->intrq_r() ? 0x80 : 0);
+ }
+
+ return 0xff;
+}
+
+
+WRITE8_MEMBER(msx_slot_disk5_device::io_write)
+{
+ switch (offset)
+ {
+ case 0x00:
+ m_fdc->cmd_w(data);
+ break;
+
+ case 0x01:
+ m_fdc->track_w(data);
+ break;
+
+ case 0x02:
+ m_fdc->sector_w(data);
+ break;
+
+ case 0x03:
+ m_fdc->data_w(data);
+ break;
+
+ case 0x04:
+ set_control(data);
+ break;
+ }
+}
+
+
+
+msx_slot_disk6_device::msx_slot_disk6_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : msx_slot_wd_disk_device(mconfig, MSX_SLOT_DISK6, "MSX Internal floppy type 6", tag, owner, clock, "msx_slot_disk6", __FILE__)
+ , m_side_motor(0)
+ , m_drive_select0(0)
+ , m_drive_select1(0)
+{
+}
+
+
+void msx_slot_disk6_device::device_start()
+{
+ msx_slot_wd_disk_device::device_start();
+
+ save_item(NAME(m_side_motor));
+ save_item(NAME(m_drive_select0));
+ save_item(NAME(m_drive_select1));
+
+ machine().save().register_postload(save_prepost_delegate(FUNC(msx_slot_disk6_device::post_load), this));
+}
+
+
+void msx_slot_disk6_device::device_reset()
+{
+ m_fdc->dden_w(false);
+}
+
+
+void msx_slot_disk6_device::post_load()
+{
+ select_drive();
+}
+
+
+void msx_slot_disk6_device::select_drive()
+{
+ if (m_drive_select1)
+ {
+ m_floppy = m_floppy1 ? m_floppy1->get_device() : NULL;
+ if (!m_floppy)
+ {
+ m_drive_select1 = 0;
+ }
+ }
+
+ if (m_drive_select0)
+ {
+ m_floppy = m_floppy0 ? m_floppy0->get_device() : NULL;
+ if (!m_floppy)
+ {
+ m_drive_select0 = 0;
+ }
+ }
+
+ m_fdc->set_floppy(m_floppy);
+
+ set_side_motor();
+}
+
+
+void msx_slot_disk6_device::set_side_motor()
+{
+ if (m_floppy)
+ {
+ m_floppy->mon_w((m_side_motor & 0x02) ? 0 : 1);
+ m_floppy->ss_w(m_side_motor & 0x01);
+ }
+}
+
+
+READ8_MEMBER(msx_slot_disk6_device::read)
+{
+ switch (offset)
+ {
+ case 0x7ff0: // status?
+ case 0x7ff8:
+ return m_fdc->status_r();
+
+ case 0x7ff1: // track?
+ case 0x7ff9:
+ return m_fdc->track_r();
+
+ case 0x7ff2: // sector?
+ case 0x7ffa:
+ return m_fdc->sector_r();
+
+ case 0x7ff3: // data?
+ case 0x7ffb:
+ return m_fdc->data_r();
+
+ case 0x7ff4:
+ case 0x7ffc:
+ // bit 0 = side control
+ // bit 1 = motor control
+ return 0xfc | m_side_motor;
+ break;
+
+ // This reads back a 1 in bit 0 if drive0 is present and selected
+ case 0x7ff5:
+ case 0x7ffd:
+ return 0xfe | m_drive_select0;
+
+ // This reads back a 1 in bit 0 if drive1 is present and selected
+ case 0x7ff6:
+ case 0x7ffe:
+ return 0xfe | m_drive_select1;
+
+ case 0x7ff7:
+ case 0x7fff:
+ return 0x3f | (m_fdc->intrq_r() ? 0 : 0x40) | (m_fdc->drq_r() ? 0 : 0x80);
+ }
+
+ return msx_slot_rom_device::read(space, offset);
+}
+
+
+WRITE8_MEMBER(msx_slot_disk6_device::write)
+{
+ switch (offset)
+ {
+ case 0x7ff0: // cmd?
+ case 0x7ff8:
+ m_fdc->cmd_w(data);
+ break;
+
+ case 0x7ff1: // track?
+ case 0x7ff9:
+ m_fdc->track_w(data);
+ break;
+
+ case 0x7ff2: // sector?
+ case 0x7ffa:
+ m_fdc->sector_w(data);
+ break;
+
+ case 0x7ff3: // data?
+ case 0x7ffb:
+ m_fdc->data_w(data);
+ break;
+
+ // Side and motort control
+ // bit 0 = side select
+ // bit 1 = motor on/off
+ case 0x7ff4:
+ case 0x7ffc:
+ m_side_motor = data;
+ set_side_motor();
+ break;
+
+ // bit 0 - select drive 0
+ case 0x7ff5:
+ case 0x7ffd:
+ m_drive_select0 = data;
+ select_drive();
+ break;
+
+ // bit 1 - select drive 1
+ case 0x7ff6:
+ case 0x7ffe:
+ m_drive_select1 = data;
+ select_drive();
+ break;
+
+ default:
+ logerror("msx_slot_disk6_device::write: Unmapped write writing %02x to %04x\n", data, offset);
+ break;
+ }
+}