summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author Michael Zapf <Michael.Zapf@mizapf.de>2015-04-19 23:09:05 +0200
committer Michael Zapf <Michael.Zapf@mizapf.de>2015-04-20 14:33:19 +0200
commit1ad65b58ff532505885794cc9ac7e9693deb57dc (patch)
tree1d708a7e3e24ab4f86d153114885dc3697a9f996 /src
parent0aebc8e54e2ad38ab6e1aec77f8cc43afc1cdda5 (diff)
ti99: ST225 emulation
Diffstat (limited to 'src')
-rw-r--r--src/emu/audit.c2
-rw-r--r--src/emu/bus/ti99_peb/hfdc.c270
-rw-r--r--src/emu/bus/ti99_peb/hfdc.h52
-rw-r--r--src/emu/bus/ti99_peb/peribox.c7
-rw-r--r--src/emu/imagedev/harddriv.c14
-rw-r--r--src/emu/imagedev/harddriv.h2
-rw-r--r--src/emu/machine/hdc9234.c111
-rw-r--r--src/emu/machine/hdc9234.h10
-rw-r--r--src/emu/machine/smc92x4.c2
-rw-r--r--src/emu/machine/smc92x4.h4
-rw-r--r--src/emu/machine/ti99_hd.c249
-rw-r--r--src/emu/machine/ti99_hd.h76
12 files changed, 627 insertions, 172 deletions
diff --git a/src/emu/audit.c b/src/emu/audit.c
index 72bb77684d2..fe207522c02 100644
--- a/src/emu/audit.c
+++ b/src/emu/audit.c
@@ -11,7 +11,7 @@
#include "emu.h"
#include "emuopts.h"
#include "audit.h"
-#include "harddisk.h"
+#include "chd.h"
#include "sound/samples.h"
diff --git a/src/emu/bus/ti99_peb/hfdc.c b/src/emu/bus/ti99_peb/hfdc.c
index a8cab9594ce..14c397872a2 100644
--- a/src/emu/bus/ti99_peb/hfdc.c
+++ b/src/emu/bus/ti99_peb/hfdc.c
@@ -74,12 +74,12 @@
#define CLK_ADDR 0x0fe0
#define RAM_ADDR 0x1000
-#define TRACE_EMU 0
+#define TRACE_EMU 1
#define TRACE_CRU 0
#define TRACE_COMP 0
#define TRACE_RAM 0
#define TRACE_ROM 0
-#define TRACE_LINES 0
+#define TRACE_LINES 1
#define TRACE_MOTOR 0
#define TRACE_DMA 0
#define TRACE_INT 0
@@ -499,12 +499,32 @@ void myarc_hfdc_device::device_timer(emu_timer &timer, device_timer_id id, int p
*/
void myarc_hfdc_device::floppy_index_callback(floppy_image_device *floppy, int state)
{
- if (TRACE_LINES) if (state==1) logerror("%s: Index pulse\n", tag());
+ if (TRACE_LINES) if (state==1) logerror("%s: Floppy index pulse\n", tag());
// m_status_latch = (state==ASSERT_LINE)? (m_status_latch | HDC_DS_INDEX) : (m_status_latch & ~HDC_DS_INDEX);
set_bits(m_status_latch, HDC_DS_INDEX, (state==ASSERT_LINE));
signal_drive_status();
}
+/*
+ This is called back from the hard disk when an index hole is passing by.
+*/
+void myarc_hfdc_device::harddisk_index_callback(mfm_harddisk_device *harddisk, int state)
+{
+ /* if (TRACE_LINES) */ if (state==1) logerror("%s: HD seek complete\n", tag());
+ set_bits(m_status_latch, HDC_DS_SKCOM, (state==ASSERT_LINE));
+ signal_drive_status();
+}
+
+/*
+ This is called back from the hard disk when seek_complete becomes asserted.
+*/
+void myarc_hfdc_device::harddisk_skcom_callback(mfm_harddisk_device *harddisk, int state)
+{
+ /* if (TRACE_LINES) */ if (state==1) logerror("%s: HD index pulse\n", tag());
+ set_bits(m_status_latch, HDC_DS_INDEX, (state==ASSERT_LINE));
+ signal_drive_status();
+}
+
void myarc_hfdc_device::set_bits(UINT8& byte, int mask, bool set)
{
if (set) byte |= mask;
@@ -512,18 +532,16 @@ void myarc_hfdc_device::set_bits(UINT8& byte, int mask, bool set)
}
/*
- Calculate the logarithm. This is needed to determine the index of a drive.
- Returns -1 for value=0
+ Maps the set bit to an index. The rightmost 1 bit is significant. When no
+ bit is set, returns -1.
*/
-int myarc_hfdc_device::slog2(int value)
+int myarc_hfdc_device::bit_to_index(int value)
{
- int i=-1;
- while (value!=0)
- {
- value >>= 1;
- i++;
- }
- return i;
+ if (value & 0x01) return 0;
+ if (value & 0x02) return 1;
+ if (value & 0x04) return 2;
+ if (value & 0x08) return 3;
+ return -1;
}
/*
@@ -554,7 +572,19 @@ void myarc_hfdc_device::signal_drive_status()
// Check for TRK00*
if ((m_current_floppy != NULL) && (!m_current_floppy->trk00_r()))
- reply |= 0x10;
+ reply |= HDC_DS_TRK00;
+ }
+ else
+ {
+ if ((m_output1_latch & 0xe0)!=0)
+ {
+ if (m_current_harddisk->ready_r()==ASSERT_LINE)
+ {
+ m_status_latch |= HDC_DS_READY;
+ set_bits(m_status_latch, HDC_DS_SKCOM, m_current_harddisk->seek_complete_r()==ASSERT_LINE);
+ set_bits(m_status_latch, HDC_DS_TRK00, m_current_harddisk->trk00_r()==ASSERT_LINE);
+ }
+ }
}
// If WDS is selected but not connected, WDS.ready* and WDS.seekComplete* are 1, so Ready=SeekComplete=0
@@ -598,27 +628,18 @@ WRITE8_MEMBER( myarc_hfdc_device::auxbus_out )
m_output1_latch = data;
- if ((data & 0x10) != 0)
- {
- // Floppy selected
- connect_floppy_unit(slog2(data & 0x0f));
- }
+ if ((data & 0x10) != 0) connect_floppy_unit(bit_to_index(data & 0x0f)); // Floppy selected
else
{
- index = slog2((data>>4) & 0x0f);
- if (index == -1)
- {
- if (TRACE_LINES) logerror("%s: Unselect all HD drives\n", tag());
- connect_floppy_unit(index);
- }
- else
- {
- // HD selected
- if (TRACE_LINES) logerror("%s: Select hard disk WDS%d\n", tag(), index);
- // if (index>=0) m_hdc9234->connect_hard_drive(m_harddisk_unit[index-1]);
- }
- if (m_current_harddisk==NULL)
+ index = bit_to_index((data>>4) & 0x0f);
+
+ if (index > 0) connect_harddisk_unit(index-1); // HD selected; index >= 1
+ else
{
+ disconnect_floppy_drives();
+ disconnect_hard_drives();
+
+ // Turn off READY and SEEK COMPLETE
set_bits(m_status_latch, HDC_DS_READY | HDC_DS_SKCOM, false);
}
}
@@ -643,6 +664,13 @@ WRITE8_MEMBER( myarc_hfdc_device::auxbus_out )
m_current_floppy->dir_w((data & 0x20)==0);
m_current_floppy->stp_w((data & 0x10)==0);
}
+
+ if (m_current_harddisk != NULL)
+ {
+ // Dir = 0 -> outward
+ m_current_harddisk->direction_in_w((data & 0x20)? ASSERT_LINE : CLEAR_LINE);
+ m_current_harddisk->step_w((data & 0x10)? ASSERT_LINE : CLEAR_LINE);
+ }
// We are pushing the drive status after OUTPUT2
signal_drive_status();
@@ -659,52 +687,74 @@ enum
void myarc_hfdc_device::connect_floppy_unit(int index)
{
// Check if we have a new floppy
- if (index>=0)
+ if (m_floppy_unit[index] != m_current_floppy)
{
- if (m_floppy_unit[index] != m_current_floppy)
- {
- if (TRACE_LINES) logerror("%s: Select floppy drive DSK%d\n", tag(), index+1);
- if (m_current_floppy != NULL)
- {
- // Disconnect old drive from index line
- if (TRACE_LINES) logerror("%s: Disconnect previous index callback DSK%d\n", tag(), index+1);
- m_current_floppy->setup_index_pulse_cb(floppy_image_device::index_pulse_cb());
- }
- // Connect new drive
- m_current_floppy = m_floppy_unit[index];
-
- // We don't use the READY line of floppy drives.
- // READY is asserted when DSKx = 1
- // The controller fetches the state with the auxbus access
- if (TRACE_LINES) logerror("%s: Connect index callback DSK%d\n", tag(), index+1);
- if (m_current_floppy != NULL)
- m_current_floppy->setup_index_pulse_cb(floppy_image_device::index_pulse_cb(FUNC(myarc_hfdc_device::floppy_index_callback), this));
- else
- logerror("%s: Connection to DSK%d failed because no drive is connected\n", tag(), index+1);
- m_hdc9234->connect_floppy_drive(m_floppy_unit[index]);
- }
+ disconnect_floppy_drives();
+ if (TRACE_LINES) logerror("%s: Select floppy drive DSK%d\n", tag(), index+1);
+
+ // Connect new drive
+ m_current_floppy = m_floppy_unit[index];
+
+ // We don't use the READY line of floppy drives.
+ // READY is asserted when DSKx = 1
+ // The controller fetches the state with the auxbus access
+ if (TRACE_LINES) logerror("%s: Connect index callback DSK%d\n", tag(), index+1);
+ if (m_current_floppy != NULL)
+ m_current_floppy->setup_index_pulse_cb(floppy_image_device::index_pulse_cb(FUNC(myarc_hfdc_device::floppy_index_callback), this));
+ else
+ logerror("%s: Connection to DSK%d failed because no drive is connected\n", tag(), index+1);
+ m_hdc9234->connect_floppy_drive(m_floppy_unit[index]);
}
- else
+
+ // We can only run a floppy or a harddisk at a time, not both
+ disconnect_hard_drives();
+}
+
+void myarc_hfdc_device::connect_harddisk_unit(int index)
+{
+ if (m_harddisk_unit[index] != m_current_harddisk)
{
- if (TRACE_LINES) logerror("%s: Unselect all floppy drives\n", tag());
- // Disconnect current floppy
- if (m_current_floppy != NULL)
+ disconnect_hard_drives();
+ if (TRACE_LINES) logerror("%s: Select hard disk WDS%d\n", tag(), index+1);
+
+ // Connect new drive
+ m_current_harddisk = m_harddisk_unit[index];
+
+ if (TRACE_LINES) logerror("%s: Connect index callback WDS%d\n", tag(), index+1);
+ if (m_current_harddisk != NULL)
{
- m_current_floppy->setup_index_pulse_cb(floppy_image_device::index_pulse_cb());
- m_current_floppy = NULL;
+ m_current_harddisk->setup_index_pulse_cb(mfm_harddisk_device::index_pulse_cb(FUNC(myarc_hfdc_device::harddisk_index_callback), this));
+ m_current_harddisk->setup_seek_complete_cb(mfm_harddisk_device::seek_complete_cb(FUNC(myarc_hfdc_device::harddisk_skcom_callback), this));
}
+ else
+ logerror("%s: Connection to WDS%d failed because no drive is connected\n", tag(), index+1);
+ m_hdc9234->connect_hard_drive(m_current_harddisk);
}
- // The drive status is supposed to be sampled after OUTPUT2
- // signal_drive_status();
+
+ // We can only run a floppy or a harddisk at a time, not both
+ disconnect_floppy_drives();
}
-void myarc_hfdc_device::connect_harddisk_unit(int index)
+void myarc_hfdc_device::disconnect_floppy_drives()
{
-// if (index < 0)
-// {
+ if (TRACE_LINES) logerror("%s: Unselect floppy drives\n", tag());
+ // Disconnect current floppy
+ if (m_current_floppy != NULL)
+ {
+ m_current_floppy->setup_index_pulse_cb(floppy_image_device::index_pulse_cb());
+ m_current_floppy = NULL;
+ }
+}
+
+void myarc_hfdc_device::disconnect_hard_drives()
+{
+ if (TRACE_LINES) logerror("%s: Unselect hard drives\n", tag());
+ if (m_current_harddisk != NULL)
+ {
+ m_current_harddisk->setup_index_pulse_cb(mfm_harddisk_device::index_pulse_cb());
+ m_current_harddisk->setup_seek_complete_cb(mfm_harddisk_device::seek_complete_cb());
m_current_harddisk = NULL;
-// }
- // signal_drive_status();
+ }
}
/*
@@ -836,26 +886,45 @@ void myarc_hfdc_device::device_reset()
for (int i=0; i < 4; i++)
{
if (m_floppy_unit[i] != NULL)
- logerror("%s: Connector %d with %s\n", tag(), i, m_floppy_unit[i]->name());
+ logerror("%s: FD connector %d with %s\n", tag(), i+1, m_floppy_unit[i]->name());
+ else
+ logerror("%s: FD connector %d has no floppy attached\n", tag(), i+1);
+ }
+
+ for (int i=0; i < 3; i++)
+ {
+ if (m_harddisk_unit[i] != NULL)
+ logerror("%s: HD connector %d with %s\n", tag(), i+1, m_harddisk_unit[i]->name());
else
- logerror("%s: Connector %d has no floppy attached\n", tag(), i);
+ logerror("%s: HD connector %d has no drive attached\n", tag(), i+1);
}
// Disconnect all units
- connect_floppy_unit(-1);
- connect_harddisk_unit(-1);
+ disconnect_floppy_drives();
+ disconnect_hard_drives();
}
void myarc_hfdc_device::device_config_complete()
{
- for (int i=0; i < 4; i++)
+ for (int i=0; i < 3; i++)
+ {
m_floppy_unit[i] = NULL;
-
+ m_harddisk_unit[i] = NULL;
+ }
+ m_floppy_unit[3] = NULL;
+
// Seems to be null when doing a "-listslots"
- if (subdevice("f0")!=NULL) m_floppy_unit[0] = static_cast<floppy_image_device*>(subdevice("f0")->first_subdevice());
- if (subdevice("f1")!=NULL) m_floppy_unit[1] = static_cast<floppy_image_device*>(subdevice("f1")->first_subdevice());
- if (subdevice("f2")!=NULL) m_floppy_unit[2] = static_cast<floppy_image_device*>(subdevice("f2")->first_subdevice());
- if (subdevice("f3")!=NULL) m_floppy_unit[3] = static_cast<floppy_image_device*>(subdevice("f3")->first_subdevice());
+ if (subdevice("f1")!=NULL)
+ {
+ m_floppy_unit[0] = static_cast<floppy_connector*>(subdevice("f1"))->get_device();
+ m_floppy_unit[1] = static_cast<floppy_connector*>(subdevice("f2"))->get_device();
+ m_floppy_unit[2] = static_cast<floppy_connector*>(subdevice("f3"))->get_device();
+ m_floppy_unit[3] = static_cast<floppy_connector*>(subdevice("f4"))->get_device();
+
+ m_harddisk_unit[0] = static_cast<mfm_harddisk_connector*>(subdevice("h1"))->get_device();
+ m_harddisk_unit[1] = static_cast<mfm_harddisk_connector*>(subdevice("h2"))->get_device();
+ m_harddisk_unit[2] = static_cast<mfm_harddisk_connector*>(subdevice("h3"))->get_device();
+ }
}
/*
@@ -918,6 +987,11 @@ static SLOT_INTERFACE_START( hfdc_floppies )
SLOT_INTERFACE( "35hd", FLOPPY_35_HD ) // 80 tracks 1.4 MiB
SLOT_INTERFACE_END
+static SLOT_INTERFACE_START( hfdc_harddisks )
+ SLOT_INTERFACE( "generic", MFM_HD_GENERIC ) // Generic high-level emulation
+// SLOT_INTERFACE( "seagatemfm", MFM_HD_SEAGATE ) // Seagate ST-225 and others
+SLOT_INTERFACE_END
+
MACHINE_CONFIG_FRAGMENT( ti99_hfdc )
MCFG_DEVICE_ADD(FDC_TAG, HDC9234, 0)
MCFG_HDC9234_INTRQ_CALLBACK(WRITELINE(myarc_hfdc_device, intrq_w))
@@ -927,11 +1001,16 @@ MACHINE_CONFIG_FRAGMENT( ti99_hfdc )
MCFG_HDC9234_DMA_IN_CALLBACK(READ8(myarc_hfdc_device, read_buffer))
MCFG_HDC9234_DMA_OUT_CALLBACK(WRITE8(myarc_hfdc_device, write_buffer))
- MCFG_FLOPPY_DRIVE_ADD("f0", hfdc_floppies, "525dd", myarc_hfdc_device::floppy_formats)
MCFG_FLOPPY_DRIVE_ADD("f1", hfdc_floppies, "525dd", myarc_hfdc_device::floppy_formats)
- MCFG_FLOPPY_DRIVE_ADD("f2", hfdc_floppies, NULL, myarc_hfdc_device::floppy_formats)
+ MCFG_FLOPPY_DRIVE_ADD("f2", hfdc_floppies, "525dd", myarc_hfdc_device::floppy_formats)
MCFG_FLOPPY_DRIVE_ADD("f3", hfdc_floppies, NULL, myarc_hfdc_device::floppy_formats)
+ MCFG_FLOPPY_DRIVE_ADD("f4", hfdc_floppies, NULL, myarc_hfdc_device::floppy_formats)
+ // NB: Hard disks don't go without image (other than floppy drives)
+ MCFG_MFM_HARDDISK_ADD("h1", hfdc_harddisks, NULL)
+ MCFG_MFM_HARDDISK_ADD("h2", hfdc_harddisks, NULL)
+ MCFG_MFM_HARDDISK_ADD("h3", hfdc_harddisks, NULL)
+
MCFG_DEVICE_ADD(CLOCK_TAG, MM58274C, 0)
MCFG_MM58274C_MODE24(1) // 24 hour
MCFG_MM58274C_DAY1(0) // sunday
@@ -962,6 +1041,27 @@ ioport_constructor myarc_hfdc_device::device_input_ports() const
const device_type TI99_HFDC = &device_creator<myarc_hfdc_device>;
+mfm_harddisk_connector::mfm_harddisk_connector(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock):
+ device_t(mconfig, MFM_HD_CONNECTOR, "MFM hard disk connector", tag, owner, clock, "mfm_hd_connector", __FILE__),
+ device_slot_interface(mconfig, *this)
+{
+}
+
+mfm_harddisk_connector::~mfm_harddisk_connector()
+{
+}
+
+mfm_harddisk_device *mfm_harddisk_connector::get_device()
+{
+ return dynamic_cast<mfm_harddisk_device *>(get_card_device());
+}
+
+void mfm_harddisk_connector::device_start()
+{
+}
+
+const device_type MFM_HD_CONNECTOR = &device_creator<mfm_harddisk_connector>;
+
// =========================================================================
/*
@@ -1252,7 +1352,7 @@ READ8_MEMBER( myarc_hfdc_legacy_device::auxbus_in )
{
UINT8 state;
index = slog2((m_output1_latch>>4) & 0x0f)-1;
- mfm_harddisk_device *hd = m_harddisk_unit[index];
+ mfm_harddisk_legacy_device *hd = m_harddisk_unit[index];
state = hd->get_status();
if (state & MFMHD_TRACK00) reply |= DS_TRK00;
@@ -1373,6 +1473,8 @@ MACHINE_CONFIG_FRAGMENT( ti99_hfdc_legacy )
MCFG_DEVICE_ADD(CLOCK_TAG, MM58274C, 0)
MCFG_MM58274C_MODE24(1) // 24 hour
MCFG_MM58274C_DAY1(0) // sunday
+
+ MCFG_MFMHD_3_DRIVES_ADD() // add hard disks
MACHINE_CONFIG_END
ROM_START( ti99_hfdc_legacy )
@@ -1461,9 +1563,9 @@ void myarc_hfdc_legacy_device::device_reset()
m_floppy_unit[2] = static_cast<legacy_floppy_image_device *>(m_slot->get_drive(FLOPPY_2));
m_floppy_unit[3] = static_cast<legacy_floppy_image_device *>(m_slot->get_drive(FLOPPY_3));
- m_harddisk_unit[0] = static_cast<mfm_harddisk_device *>(m_slot->get_drive(MFMHD_0));
- m_harddisk_unit[1] = static_cast<mfm_harddisk_device *>(m_slot->get_drive(MFMHD_1));
- m_harddisk_unit[2] = static_cast<mfm_harddisk_device *>(m_slot->get_drive(MFMHD_2));
+ m_harddisk_unit[0] = static_cast<mfm_harddisk_legacy_device *>(subdevice(MFMHD_0));
+ m_harddisk_unit[1] = static_cast<mfm_harddisk_legacy_device *>(subdevice(MFMHD_1));
+ m_harddisk_unit[2] = static_cast<mfm_harddisk_legacy_device *>(subdevice(MFMHD_2));
if (ioport("HFDCDIP")->read()&0x55)
ti99_set_80_track_drives(TRUE);
diff --git a/src/emu/bus/ti99_peb/hfdc.h b/src/emu/bus/ti99_peb/hfdc.h
index cea2344f917..5ba2d816be1 100644
--- a/src/emu/bus/ti99_peb/hfdc.h
+++ b/src/emu/bus/ti99_peb/hfdc.h
@@ -18,11 +18,12 @@
#define __HFDC__
#define HFDC_MAX_FLOPPY 4
-#define HFDC_MAX_HARD 4
+#define HFDC_MAX_HARD 3
#include "imagedev/floppy.h"
#include "machine/mm58274c.h"
#include "machine/hdc9234.h"
+#include "machine/ti99_hd.h"
extern const device_type TI99_HFDC;
@@ -49,11 +50,13 @@ public:
DECLARE_FLOPPY_FORMATS( floppy_formats );
+protected:
+ void device_config_complete();
+
private:
void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
void device_start();
void device_reset();
- void device_config_complete();
const rom_entry *device_rom_region() const;
machine_config_constructor device_mconfig_additions() const;
@@ -63,18 +66,24 @@ private:
void debug_read(offs_t offset, UINT8* value);
void debug_write(offs_t offset, UINT8 data);
- // Callback for the index hole
+ // Callbacks for the index hole and seek complete
void floppy_index_callback(floppy_image_device *floppy, int state);
-
+ void harddisk_index_callback(mfm_harddisk_device *harddisk, int state);
+ void harddisk_skcom_callback(mfm_harddisk_device *harddisk, int state);
+
// Operate the floppy motors
void set_floppy_motors_running(bool run);
- // Connect or disconnect floppy drives
+ // Connect floppy drives
void connect_floppy_unit(int index);
- // Connect or disconnect harddisk drives
+ // Connect harddisk drives
void connect_harddisk_unit(int index);
+ // Disconnect drives
+ void disconnect_floppy_drives();
+ void disconnect_hard_drives();
+
// Pushes the drive status to the HDC
void signal_drive_status();
@@ -90,11 +99,14 @@ private:
// Link to the attached floppy drives
floppy_image_device* m_floppy_unit[4];
+ // Link to the attached hard disks
+ mfm_harddisk_device* m_harddisk_unit[3];
+
// Currently selected floppy drive
floppy_image_device* m_current_floppy;
// Currently selected hard drive
- void* m_current_harddisk;
+ mfm_harddisk_device* m_current_harddisk;
// True: Access to DIP switch settings, false: access to line states
bool m_see_switches;
@@ -159,8 +171,8 @@ private:
// Signal motor_on. When TRUE, makes all drives turning.
line_state m_MOTOR_ON;
- // Calculates a simple version of a binary logarithm
- int slog2(int value);
+ // Calculates the index from the bit
+ int bit_to_index(int value);
// Utility function to set or unset bits in a byte
void set_bits(UINT8& byte, int mask, bool set);
@@ -170,6 +182,26 @@ private:
int m_readyflags;
};
+/* Connector for a MFM hard disk. See also floppy.c */
+class mfm_harddisk_connector : public device_t,
+ public device_slot_interface
+{
+public:
+ mfm_harddisk_connector(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+ ~mfm_harddisk_connector();
+
+ mfm_harddisk_device *get_device();
+
+protected:
+ void device_start();
+};
+
+extern const device_type MFM_HD_CONNECTOR;
+
+#define MCFG_MFM_HARDDISK_ADD(_tag, _slot_intf, _def_slot) \
+ MCFG_DEVICE_ADD(_tag, MFM_HD_CONNECTOR, 0) \
+ MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, false);
+
// =========================================================================
/*
@@ -250,7 +282,7 @@ private:
legacy_floppy_image_device* m_floppy_unit[HFDC_MAX_FLOPPY];
/* Connected harddisk drives. */
- mfm_harddisk_device* m_harddisk_unit[HFDC_MAX_HARD];
+ mfm_harddisk_legacy_device* m_harddisk_unit[HFDC_MAX_HARD];
/* DMA address latch */
UINT32 m_dma_address;
diff --git a/src/emu/bus/ti99_peb/peribox.c b/src/emu/bus/ti99_peb/peribox.c
index bcbc77b178c..8584cc1b189 100644
--- a/src/emu/bus/ti99_peb/peribox.c
+++ b/src/emu/bus/ti99_peb/peribox.c
@@ -467,8 +467,6 @@ MACHINE_CONFIG_FRAGMENT( peribox_device )
MCFG_DEVICE_ADD(FLOPPY_3, LEGACY_FLOPPY, 0)
MCFG_DEVICE_CONFIG(ti99_4_floppy_interface)
MCFG_LEGACY_FLOPPY_IDX_CB(WRITELINE(peribox_device, indexhole))
-
- MCFG_MFMHD_3_DRIVES_ADD()
MACHINE_CONFIG_END
machine_config_constructor peribox_device::device_mconfig_additions() const
@@ -536,7 +534,6 @@ MACHINE_CONFIG_FRAGMENT( peribox_gen_device )
MCFG_DEVICE_ADD(FLOPPY_3, LEGACY_FLOPPY, 0)
MCFG_DEVICE_CONFIG(ti99_4_floppy_interface)
MCFG_LEGACY_FLOPPY_IDX_CB(WRITELINE(peribox_device, indexhole))
- MCFG_MFMHD_3_DRIVES_ADD()
MACHINE_CONFIG_END
machine_config_constructor peribox_gen_device::device_mconfig_additions() const
@@ -589,7 +586,6 @@ MACHINE_CONFIG_FRAGMENT( peribox_998_device )
MCFG_DEVICE_ADD(FLOPPY_3, LEGACY_FLOPPY, 0)
MCFG_DEVICE_CONFIG(ti99_4_floppy_interface)
MCFG_LEGACY_FLOPPY_IDX_CB(WRITELINE(peribox_device, indexhole))
- MCFG_MFMHD_3_DRIVES_ADD()
MACHINE_CONFIG_END
machine_config_constructor peribox_998_device::device_mconfig_additions() const
@@ -643,7 +639,6 @@ MACHINE_CONFIG_FRAGMENT( peribox_sg_device )
MCFG_DEVICE_ADD(FLOPPY_3, LEGACY_FLOPPY, 0)
MCFG_DEVICE_CONFIG(ti99_4_floppy_interface)
MCFG_LEGACY_FLOPPY_IDX_CB(WRITELINE(peribox_device, indexhole))
- MCFG_MFMHD_3_DRIVES_ADD()
MACHINE_CONFIG_END
machine_config_constructor peribox_sg_device::device_mconfig_additions() const
@@ -651,7 +646,6 @@ machine_config_constructor peribox_sg_device::device_mconfig_additions() const
return MACHINE_CONFIG_NAME( peribox_sg_device );
}
-
/****************************************************************************
Another variant of the box; used for the TI with EVPC. The EVPC is
obviously required.
@@ -684,7 +678,6 @@ MACHINE_CONFIG_FRAGMENT( peribox_ev_device )
MCFG_DEVICE_ADD(FLOPPY_3, LEGACY_FLOPPY, 0)
MCFG_DEVICE_CONFIG(ti99_4_floppy_interface)
MCFG_LEGACY_FLOPPY_IDX_CB(WRITELINE(peribox_device, indexhole))
- MCFG_MFMHD_3_DRIVES_ADD()
MACHINE_CONFIG_END
machine_config_constructor peribox_ev_device::device_mconfig_additions() const
diff --git a/src/emu/imagedev/harddriv.c b/src/emu/imagedev/harddriv.c
index 1f61bc6b5a9..48fa65500df 100644
--- a/src/emu/imagedev/harddriv.c
+++ b/src/emu/imagedev/harddriv.c
@@ -48,6 +48,20 @@ harddisk_image_device::harddisk_image_device(const machine_config &mconfig, cons
}
//-------------------------------------------------
+// harddisk_image_device - constructor for subclasses
+//-------------------------------------------------
+harddisk_image_device::harddisk_image_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)
+ : device_t(mconfig, type, name, tag, owner, clock, shortname, source),
+ device_image_interface(mconfig, *this),
+ m_chd(NULL),
+ m_hard_disk_handle(NULL),
+ m_device_image_load(device_image_load_delegate()),
+ m_device_image_unload(device_image_func_delegate()),
+ m_interface(NULL)
+{
+}
+
+//-------------------------------------------------
// harddisk_image_device - destructor
//-------------------------------------------------
diff --git a/src/emu/imagedev/harddriv.h b/src/emu/imagedev/harddriv.h
index 6ec48d327fb..84c2a37e1ff 100644
--- a/src/emu/imagedev/harddriv.h
+++ b/src/emu/imagedev/harddriv.h
@@ -51,6 +51,8 @@ public:
chd_file *get_chd_file();
protected:
+ harddisk_image_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);
+
// device-level overrides
virtual void device_config_complete();
virtual void device_start();
diff --git a/src/emu/machine/hdc9234.c b/src/emu/machine/hdc9234.c
index 6267e184ad7..d6b8dd05f3c 100644
--- a/src/emu/machine/hdc9234.c
+++ b/src/emu/machine/hdc9234.c
@@ -24,37 +24,37 @@
#include "hdc9234.h"
// Per-command debugging
-#define TRACE_SELECT 0
-#define TRACE_STEP 0
-#define TRACE_RESTORE 0
-#define TRACE_SUBSTATES 0
-#define TRACE_READ 0
-#define TRACE_WRITE 0
-#define TRACE_READREG 0
-#define TRACE_SETREG 0
-#define TRACE_SETPTR 0
-#define TRACE_FORMAT 0
-#define TRACE_READTRACK 0
+#define TRACE_SELECT 1
+#define TRACE_STEP 1
+#define TRACE_RESTORE 1
+#define TRACE_SUBSTATES 1
+#define TRACE_READ 1
+#define TRACE_WRITE 1
+#define TRACE_READREG 1
+#define TRACE_SETREG 1
+#define TRACE_SETPTR 1
+#define TRACE_FORMAT 1
+#define TRACE_READTRACK 1
// Common states
-#define TRACE_READID 0
-#define TRACE_VERIFY 0
-#define TRACE_TRANSFER 0
+#define TRACE_READID 1
+#define TRACE_VERIFY 1
+#define TRACE_TRANSFER 1
// Live states debugging
-#define TRACE_LIVE 0
-#define TRACE_SHIFT 0
-#define TRACE_SYNC 0
+#define TRACE_LIVE 1
+#define TRACE_SHIFT 1
+#define TRACE_SYNC 1
// Misc debugging
#define TRACE_DELAY 0
-#define TRACE_INT 0
-#define TRACE_LINES 0
-#define TRACE_INDEX 0
-#define TRACE_DMA 0
-#define TRACE_DONE 0
-#define TRACE_FAIL 0
-#define TRACE_AUXBUS 0
+#define TRACE_INT 1
+#define TRACE_LINES 1
+#define TRACE_INDEX 1
+#define TRACE_DMA 1
+#define TRACE_DONE 1
+#define TRACE_FAIL 1
+#define TRACE_AUXBUS 1
#define TRACE_DETAIL 0
@@ -239,8 +239,8 @@ enum
enum
{
GEN_TIMER = 1,
- COM_TIMER,
- LIVE_TIMER
+ COM_TIMER /*,
+ LIVE_TIMER */
};
/*
@@ -1027,6 +1027,7 @@ void hdc9234_device::drive_deselect()
{
if (TRACE_SELECT) logerror("%s: DESELECT command\n", tag());
m_selected_drive_number = NODRIVE;
+ m_output1 = 0x00;
set_command_done(TC_SUCCESS);
}
@@ -1066,7 +1067,7 @@ void hdc9234_device::restore_drive()
// Track 0 has not been reached yet
if ((m_register_r[DRIVE_STATUS] & HDC_DS_READY)==0)
{
- if (TRACE_RESTORE) logerror("%s: restore command: drive not ready\n", tag());
+ if (TRACE_RESTORE) logerror("%s: restore command: Drive not ready\n", tag());
// Does not look like a success, but this takes into account
// that if a drive is not connected we do not want an error message
cont = SUCCESS;
@@ -1081,6 +1082,7 @@ void hdc9234_device::restore_drive()
// When we have buffered steps, the seek limit will be reached
// before TRK00 is asserted. In that case we have to wait for
// SEEK_COMPLETE. We also wait as soon as TRK00 is asserted.
+ if (TRACE_RESTORE) logerror("%s: restore using buffered steps\n", tag());
wait_line(SEEKCOMP_LINE, ASSERT_LINE, SEEK_COMPLETE, false);
cont = WAIT;
}
@@ -1809,7 +1811,8 @@ void hdc9234_device::live_start(int state)
void hdc9234_device::live_run()
{
- live_run_until(attotime::never);
+ if (using_floppy()) live_run_until(attotime::never);
+ else live_run_hd_until(attotime::never);
}
/*
@@ -1817,6 +1820,8 @@ void hdc9234_device::live_run()
the requested data are read.
limit: if unlimited (attotime::never), run up to the end of the track and wait there
otherwise, used to replay the read/write operation up to the point where the event happened
+
+ THIS IS THE FLOPPY-ONLY LIVE_RUN
*/
void hdc9234_device::live_run_until(attotime limit)
{
@@ -2623,6 +2628,40 @@ void hdc9234_device::live_run_until(attotime limit)
}
/*
+ The main method of the live state machine. We stay in this method until
+ the requested data are read.
+ limit: if unlimited (attotime::never), run up to the end of the track and wait there
+ otherwise, used to replay the read/write operation up to the point where the event happened
+
+ THIS IS THE HARDDISK-ONLY LIVE_RUN
+*/
+void hdc9234_device::live_run_hd_until(attotime limit)
+{
+ int slot = 0;
+ logerror("%s: live_run_hd\n", tag());
+
+ if (m_live_state.state == IDLE || m_live_state.next_state != -1)
+ return;
+
+ if (TRACE_LIVE)
+ {
+ if (limit == attotime::never)
+ logerror("%s: [%s] live_run_hd, live_state=%d, mode=%s\n", tag(), tts(m_live_state.time).cstr(), m_live_state.state, fm_mode()? "FM":"MFM");
+ else
+ logerror("%s: [%s] live_run_hd until %s, live_state=%d, mode=%s\n", tag(), tts(m_live_state.time).cstr(), tts(limit).cstr(), m_live_state.state, fm_mode()? "FM":"MFM");
+ }
+ while (true)
+ {
+ switch (m_live_state.state)
+ {
+ case SEARCH_IDAM:
+ break;
+ }
+ return;
+ }
+}
+
+/*
Synchronize the live position on the track with the real time.
Results in a new checkpoint and a live position at machine time or behind.
As a side effect, portions of the track may be re-read
@@ -3269,7 +3308,7 @@ void hdc9234_device::auxbus_out()
m_output2 = (m_output2 & 0xb0) | desired_head();
if (m_reduced_write_current) m_output2 |= OUT2_REDWRT;
- if (TRACE_AUXBUS) logerror("%s: Setting OUTPUT2 to %02x\n", tag(), m_output2);
+ if (TRACE_AUXBUS) logerror("%s: [%s] Setting OUTPUT1=%02x, OUTPUT2=%02x\n", tag(), ttsn().cstr(), m_output1, m_output2);
if (m_output1 != m_output1_old || m_output2 != m_output2_old)
{
@@ -3338,6 +3377,14 @@ void hdc9234_device::connect_floppy_drive(floppy_image_device* floppy)
}
/*
+ Connect the current hard drive.
+*/
+void hdc9234_device::connect_hard_drive(mfm_harddisk_device* harddisk)
+{
+ m_harddisk = harddisk;
+}
+
+/*
Clock divider. This input line actually belongs to the data separator which
is a separate circuit. Maybe we will take it out of this implementation
at some time and make it a device of its own.
@@ -3363,9 +3410,9 @@ void hdc9234_device::device_timer(emu_timer &timer, device_timer_id id, int para
case COM_TIMER:
process_command();
break;
- case LIVE_TIMER:
+ /* case LIVE_TIMER:
live_run();
- break;
+ break; */
}
}
@@ -3393,7 +3440,7 @@ void hdc9234_device::device_start()
// allocate timers
m_timer = timer_alloc(GEN_TIMER);
m_cmd_timer = timer_alloc(COM_TIMER);
- m_live_timer = timer_alloc(LIVE_TIMER);
+ // m_live_timer = timer_alloc(LIVE_TIMER);
m_live_state.state = IDLE;
}
diff --git a/src/emu/machine/hdc9234.h b/src/emu/machine/hdc9234.h
index cd96fdc7db2..d140ae62e46 100644
--- a/src/emu/machine/hdc9234.h
+++ b/src/emu/machine/hdc9234.h
@@ -10,6 +10,7 @@
#include "emu.h"
#include "imagedev/floppy.h"
#include "fdc_pll.h"
+#include "ti99_hd.h"
extern const device_type HDC9234;
@@ -109,6 +110,9 @@ public:
// is changed outside of the controller, and by this way we let it know.
void connect_floppy_drive(floppy_image_device *floppy);
+ // Used to reconfigure the drive connections. See connect_floppy_drive.
+ void connect_hard_drive(mfm_harddisk_device *harddisk);
+
protected:
void device_start();
void device_reset();
@@ -134,6 +138,9 @@ private:
// Currently connected floppy
floppy_image_device* m_floppy;
+ // Currently connected harddisk
+ mfm_harddisk_device* m_harddisk;
+
// internal register OUTPUT1
UINT8 m_output1, m_output1_old;
@@ -220,6 +227,9 @@ private:
// Analyses the track until the given time
void live_run_until(attotime limit);
+
+ // Same for hard disks
+ void live_run_hd_until(attotime limit);
// Live run until next index pulse
void live_run();
diff --git a/src/emu/machine/smc92x4.c b/src/emu/machine/smc92x4.c
index a6581dd6baf..e6091ef14f9 100644
--- a/src/emu/machine/smc92x4.c
+++ b/src/emu/machine/smc92x4.c
@@ -1991,7 +1991,7 @@ void smc92x4_device::connect_floppy_drive(legacy_floppy_image_device *drive)
else LOG("smc92x4: Connect drive %s\n", drive->tag());
}
}
-void smc92x4_device::connect_hard_drive(mfm_harddisk_device *drive)
+void smc92x4_device::connect_hard_drive(mfm_harddisk_legacy_device *drive)
{
m_harddisk = drive;
if (VERBOSE>3)
diff --git a/src/emu/machine/smc92x4.h b/src/emu/machine/smc92x4.h
index 5140929b151..defe39100ee 100644
--- a/src/emu/machine/smc92x4.h
+++ b/src/emu/machine/smc92x4.h
@@ -99,7 +99,7 @@ public:
// Used to reconfigure the drive connections. Drive selection is done
// using the select lines and maybe also the user-programmable outputs.
void connect_floppy_drive(legacy_floppy_image_device *drive);
- void connect_hard_drive(mfm_harddisk_device *drive);
+ void connect_hard_drive(mfm_harddisk_legacy_device *drive);
void reset();
@@ -223,7 +223,7 @@ private:
// We expect the embedding board to replace the drive according to the
// select lines.
legacy_floppy_image_device *m_drive;
- mfm_harddisk_device *m_harddisk;
+ mfm_harddisk_legacy_device *m_harddisk;
};
#endif
diff --git a/src/emu/machine/ti99_hd.c b/src/emu/machine/ti99_hd.c
index 77d37ca07de..90cb6701079 100644
--- a/src/emu/machine/ti99_hd.c
+++ b/src/emu/machine/ti99_hd.c
@@ -2,23 +2,21 @@
// copyright-holders:Michael Zapf
/*************************************************************************
- Hard disk support
-
- This device wraps the plain image device as that device does not allow
- for internal states (like head position)
- The plain device is a subdevice ("drive") of this device, so we
- get names like "mfmhd0:drive"
+ Hard disk emulation
Michael Zapf
April 2010
February 2012: Rewritten as class
+ April 2015: Rewritten with deeper emulation detail
+ References:
+ [1] ST225 OEM Manual, Seagate
+
**************************************************************************/
#include "emu.h"
#include "formats/imageutl.h"
#include "harddisk.h"
-#include "smc92x4.h"
#include "ti99_hd.h"
@@ -33,8 +31,211 @@
#define GAP4 340
#define SYNC 13
-mfm_harddisk_device::mfm_harddisk_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
-: device_t(mconfig, TI99_MFMHD, "MFM Harddisk", tag, owner, clock, "mfm_harddisk", __FILE__)
+enum
+{
+ INDEX_TM = 0,
+ SPINUP_TM,
+ SEEK_TM
+};
+
+enum
+{
+ STEP_COLLECT = 0,
+ STEP_MOVING,
+ STEP_SETTLE
+};
+
+mfm_harddisk_device::mfm_harddisk_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)
+ : harddisk_image_device(mconfig, type, name, tag, owner, clock, shortname, source),
+ device_slot_card_interface(mconfig, *this)
+{
+}
+
+void mfm_harddisk_device::device_start()
+{
+ m_index_timer = timer_alloc(INDEX_TM);
+ m_spinup_timer = timer_alloc(SPINUP_TM);
+ m_seek_timer = timer_alloc(SEEK_TM);
+
+ // MFM drives have a revolution rate of 3600 rpm (i.e. 60/sec)
+ m_index_timer->adjust(attotime::from_hz(60), 0, attotime::from_hz(60));
+
+ // Spinup may take up to 24 seconds
+ m_spinup_timer->adjust(attotime::from_msec(8000));
+
+ m_current_cylinder = 10; // for test purpose
+}
+
+void mfm_harddisk_device::device_reset()
+{
+ m_autotruncation = false;
+ m_ready = false;
+ m_seek_complete = true;
+ m_seek_inward = false;
+ m_track_delta = 0;
+ m_step_line = CLEAR_LINE;
+}
+
+void mfm_harddisk_device::setup_index_pulse_cb(index_pulse_cb cb)
+{
+ m_index_pulse_cb = cb;
+}
+
+void mfm_harddisk_device::setup_seek_complete_cb(seek_complete_cb cb)
+{
+ m_seek_complete_cb = cb;
+}
+
+void mfm_harddisk_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ switch (id)
+ {
+ case INDEX_TM:
+ /* Simple index hole handling. We assume that there is only a short pulse. */
+ if (!m_index_pulse_cb.isnull())
+ {
+ m_index_pulse_cb(this, ASSERT_LINE);
+ m_index_pulse_cb(this, CLEAR_LINE);
+ }
+ break;
+ case SPINUP_TM:
+ m_ready = true;
+ logerror("%s: Spinup complete, drive is ready\n", tag());
+ break;
+ case SEEK_TM:
+ switch (m_step_phase)
+ {
+ case STEP_COLLECT:
+ // Collect timer has expired; start moving head
+ head_move();
+ break;
+ case STEP_MOVING:
+ // Head has reached final position
+ // Check whether we have a new delta
+ if (m_track_delta == 0)
+ {
+ // Start the settle timer
+ m_step_phase = STEP_SETTLE;
+ m_seek_timer->adjust(attotime::from_usec(16800));
+ }
+ break;
+ case STEP_SETTLE:
+ // Do we have new step pulses?
+ if (m_track_delta != 0) head_move();
+ else
+ {
+ // Seek completed
+ m_seek_complete = true;
+ m_seek_complete_cb(this, ASSERT_LINE);
+ m_step_phase = STEP_COLLECT;
+ }
+ break;
+ }
+ }
+}
+
+void mfm_harddisk_device::head_move()
+{
+ int disttime = m_track_delta*200;
+ if (disttime < 0) disttime = -disttime;
+ m_step_phase = STEP_MOVING;
+ m_seek_timer->adjust(attotime::from_usec(disttime));
+ // We pretend that we already arrived
+ // TODO: Check auto truncation?
+ m_current_cylinder += m_track_delta;
+ if (m_current_cylinder < 0) m_current_cylinder = 0;
+ if (m_current_cylinder > 670) m_current_cylinder = 670;
+ m_track_delta = 0;
+}
+
+void mfm_harddisk_device::direction_in_w(line_state line)
+{
+ m_seek_inward = (line == ASSERT_LINE);
+ logerror("%s: Setting seek direction %s\n", tag(), m_seek_inward? "inward" : "outward");
+}
+
+/*
+ According to the specs [1]:
+
+ "4.3.1 BUFFERED SEEK: To minimize access time, pulses may be issued at an
+ accelerated rate and buffered in a counter. Initiation of a seek starts
+ immediately after the first pulse is received. Head motion occurs during
+ pulse accumulation, and the seek is completed following receipt of all pulses."
+
+ "8.1.3 SEEKING: Upon receiving a Step pulse, the MPU (microprocessor unit)
+ pauses for 250 usec to allow for additional pulses before executing the seek
+ operation. Every incoming pulse resets the 250 usec timer. The seek will
+ not begin until the last pulse is received."
+
+ WTF? Oh come on, Seagate, be consistent at least in a single document.
+
+ ================================
+
+ Step behaviour:
+ During all waiting times, further step_w invocations increase the counter
+
+ - Leading edge increments the counter c and sets the timer to 250us (mode=collect)
+ - When the timer expires (mode=collect):
+ (1)- Calculate the stepping time: time = c*200us; save the counter
+ - Start the timer (mode=move)
+ - When the timer expires (mode=move)
+ - Add the track delta to the current track position
+ - Subtract the delta from the current counter
+ - When the counter is not zero (pulses arrived in the meantime), go to (1)
+ - When the counter is zero, set the timer to 16.8 ms (mode=settle)
+ - When the timer expires (mode=settle)
+ - When the counter is not zero, go to (1)
+ - When the counter is zero, signal seek_complete; done
+
+ Step timing:
+ per track = 20 ms max, full seek: 150 ms max (615 tracks); both including settling time
+ We assume t(1) = 17; t(615)=140
+ t(i) = s+d*i
+ s=(615*t(1)-t(615))/614
+ d=t(1)-s
+ s=16800 us, d=200 us
+*/
+
+void mfm_harddisk_device::step_w(line_state line)
+{
+ // Leading edge
+ if (line == ASSERT_LINE && m_step_line == CLEAR_LINE)
+ {
+ if (m_seek_complete)
+ {
+ m_step_phase = STEP_COLLECT;
+ m_seek_complete = false;
+ m_seek_complete_cb(this, CLEAR_LINE);
+ }
+
+ logerror("%s: Got seek pulse; distance %d, direction %s\n", tag(), m_track_delta, m_seek_inward? "inward" : "outward");
+ // Counter will be adjusted according to the direction (+-1)
+ m_track_delta += (m_seek_inward)? +1 : -1;
+ if (m_track_delta < 0 || m_track_delta > 670)
+ {
+ logerror("%s: Excessive step pulses - doing auto-truncation\n", tag());
+ m_autotruncation = true;
+ }
+ m_seek_timer->adjust(attotime::from_usec(250));
+ }
+ m_step_line = line;
+}
+
+mfm_hd_generic_device::mfm_hd_generic_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+: mfm_harddisk_device(mconfig, MFM_HD_GENERIC, "Generic MFM hard disk (byte level)", tag, owner, clock, "mfm_harddisk", __FILE__)
+{
+}
+
+const device_type MFM_HD_GENERIC = &device_creator<mfm_hd_generic_device>;
+
+// ===========================================================================
+// Legacy implementation
+// ===========================================================================
+
+#include "smc92x4.h"
+
+mfm_harddisk_legacy_device::mfm_harddisk_legacy_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+: device_t(mconfig, TI99_MFMHD_LEG, "MFM Harddisk LEGACY", tag, owner, clock, "mfm_harddisk_leg", __FILE__)
{
}
@@ -43,7 +244,7 @@ mfm_harddisk_device::mfm_harddisk_device(const machine_config &mconfig, const ch
define idents beyond cylinder 1023, but formatting programs seem to
continue with 0xfd for cylinders between 1024 and 2047.
*/
-UINT8 mfm_harddisk_device::cylinder_to_ident(int cylinder)
+UINT8 mfm_harddisk_legacy_device::cylinder_to_ident(int cylinder)
{
if (cylinder < 256) return 0xfe;
if (cylinder < 512) return 0xff;
@@ -55,7 +256,7 @@ UINT8 mfm_harddisk_device::cylinder_to_ident(int cylinder)
/*
Returns the linear sector number, given the CHS data.
*/
-bool mfm_harddisk_device::harddisk_chs_to_lba(hard_disk_file *hdfile, int cylinder, int head, int sector, UINT32 *lba)
+bool mfm_harddisk_legacy_device::harddisk_chs_to_lba(hard_disk_file *hdfile, int cylinder, int head, int sector, UINT32 *lba)
{
const hard_disk_info *info;
@@ -77,7 +278,7 @@ bool mfm_harddisk_device::harddisk_chs_to_lba(hard_disk_file *hdfile, int cylind
}
/* Accessor functions */
-void mfm_harddisk_device::read_sector(int cylinder, int head, int sector, UINT8 *buf)
+void mfm_harddisk_legacy_device::read_sector(int cylinder, int head, int sector, UINT8 *buf)
{
UINT32 lba;
if (VERBOSE>5) LOG("ti99_hd: read_sector(%d, %d, %d)\n", cylinder, head, sector);
@@ -109,7 +310,7 @@ void mfm_harddisk_device::read_sector(int cylinder, int head, int sector, UINT8
m_status |= MFMHD_READY;
}
-void mfm_harddisk_device::write_sector(int cylinder, int head, int sector, UINT8 *buf)
+void mfm_harddisk_legacy_device::write_sector(int cylinder, int head, int sector, UINT8 *buf)
{
UINT32 lba;
if (VERBOSE>5) LOG("ti99_hd: write_sector(%d, %d, %d)\n", cylinder, head, sector);
@@ -142,7 +343,7 @@ void mfm_harddisk_device::write_sector(int cylinder, int head, int sector, UINT8
Searches a block containing number * byte, starting at the given
position. Returns the position of the first byte of the block.
*/
-int mfm_harddisk_device::find_block(const UINT8 *buffer, int start, int stop, UINT8 byte, size_t number)
+int mfm_harddisk_legacy_device::find_block(const UINT8 *buffer, int start, int stop, UINT8 byte, size_t number)
{
int i = start;
size_t current = number;
@@ -165,7 +366,7 @@ int mfm_harddisk_device::find_block(const UINT8 *buffer, int start, int stop, UI
return TI99HD_BLOCKNOTFOUND;
}
-int mfm_harddisk_device::get_track_length()
+int mfm_harddisk_legacy_device::get_track_length()
{
int count;
int size;
@@ -187,7 +388,7 @@ int mfm_harddisk_device::get_track_length()
WARNING: This function is untested! We need to create a suitable
application program for the TI which makes use of it.
*/
-void mfm_harddisk_device::read_track(int head, UINT8 *trackdata)
+void mfm_harddisk_legacy_device::read_track(int head, UINT8 *trackdata)
{
/* We assume an interleave of 3 for 32 sectors. */
int step = 3;
@@ -291,7 +492,7 @@ void mfm_harddisk_device::read_track(int head, UINT8 *trackdata)
Writes a track to the image. We need to isolate the sector contents.
This is basically done in the same way as in the SDF format in ti99_dsk.
*/
-void mfm_harddisk_device::write_track(int head, UINT8 *track_image, int data_count)
+void mfm_harddisk_legacy_device::write_track(int head, UINT8 *track_image, int data_count)
{
int current_pos = 0;
bool found;
@@ -401,7 +602,7 @@ void mfm_harddisk_device::write_track(int head, UINT8 *track_image, int data_cou
}
}
-UINT8 mfm_harddisk_device::get_status()
+UINT8 mfm_harddisk_legacy_device::get_status()
{
UINT8 status = 0;
hard_disk_file *file = m_drive->get_hard_disk_file();
@@ -422,7 +623,7 @@ UINT8 mfm_harddisk_device::get_status()
return status;
}
-void mfm_harddisk_device::seek(int direction)
+void mfm_harddisk_legacy_device::seek(int direction)
{
const hard_disk_info *info;
hard_disk_file *file = m_drive->get_hard_disk_file();
@@ -449,7 +650,7 @@ void mfm_harddisk_device::seek(int direction)
m_seeking = false;
}
-void mfm_harddisk_device::get_next_id(int head, chrn_id_hd *id)
+void mfm_harddisk_legacy_device::get_next_id(int head, chrn_id_hd *id)
{
const hard_disk_info *info;
hard_disk_file *file;
@@ -479,13 +680,13 @@ void mfm_harddisk_device::get_next_id(int head, chrn_id_hd *id)
id->flags = 0;
}
-void mfm_harddisk_device::device_start()
+void mfm_harddisk_legacy_device::device_start()
{
m_current_cylinder = 0;
m_current_head = 0;
}
-void mfm_harddisk_device::device_reset()
+void mfm_harddisk_legacy_device::device_reset()
{
m_drive = static_cast<harddisk_image_device *>(subdevice("drive"));
m_seeking = false;
@@ -497,9 +698,9 @@ MACHINE_CONFIG_FRAGMENT( mfmhd )
MCFG_HARDDISK_ADD("drive")
MACHINE_CONFIG_END
-machine_config_constructor mfm_harddisk_device::device_mconfig_additions() const
+machine_config_constructor mfm_harddisk_legacy_device::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME( mfmhd );
}
-const device_type TI99_MFMHD = &device_creator<mfm_harddisk_device>;
+const device_type TI99_MFMHD_LEG = &device_creator<mfm_harddisk_legacy_device>;
diff --git a/src/emu/machine/ti99_hd.h b/src/emu/machine/ti99_hd.h
index e3175e4723f..1090168e49f 100644
--- a/src/emu/machine/ti99_hd.h
+++ b/src/emu/machine/ti99_hd.h
@@ -17,11 +17,65 @@
#include "emu.h"
#include "imagedev/harddriv.h"
+class mfm_harddisk_device : public harddisk_image_device,
+ public device_slot_card_interface
+{
+public:
+ mfm_harddisk_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);
+
+ typedef delegate<void (mfm_harddisk_device*, int)> index_pulse_cb;
+ typedef delegate<void (mfm_harddisk_device*, int)> seek_complete_cb;
+
+ void setup_index_pulse_cb(index_pulse_cb cb);
+ void setup_seek_complete_cb(seek_complete_cb cb);
+
+ // Active low lines. We're using ASSERT=0 / CLEAR=1
+ line_state ready_r() { return m_ready? ASSERT_LINE : CLEAR_LINE; }
+ line_state seek_complete_r() { return m_seek_complete? ASSERT_LINE : CLEAR_LINE; } ;
+ line_state trk00_r() { return m_current_cylinder==0? ASSERT_LINE : CLEAR_LINE; }
+
+ // Step
+ void step_w(line_state line);
+ void direction_in_w(line_state line);
+
+protected:
+ void device_start();
+ void device_reset();
+ emu_timer *m_index_timer, *m_spinup_timer, *m_seek_timer;
+ index_pulse_cb m_index_pulse_cb;
+ seek_complete_cb m_seek_complete_cb;
+ void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
+
+private:
+ bool m_ready;
+ int m_current_cylinder;
+ int m_track_delta;
+ int m_step_phase;
+ bool m_seek_complete;
+ bool m_seek_inward;
+ bool m_seeking;
+ bool m_autotruncation;
+ line_state m_step_line; // keep the last state
+
+ void head_move();
+};
+
+class mfm_hd_generic_device : public mfm_harddisk_device
+{
+public:
+ mfm_hd_generic_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+};
+
+extern const device_type MFM_HD_GENERIC;
+
+// ===========================================================================
+// Legacy implementation
+// ===========================================================================
#define MFMHD_0 "mfmhd0"
#define MFMHD_1 "mfmhd1"
#define MFMHD_2 "mfmhd2"
-extern const device_type TI99_MFMHD;
+extern const device_type TI99_MFMHD_LEG;
/*
Needed to adapt to higher cylinder numbers. Floppies do not have such
@@ -37,10 +91,10 @@ struct chrn_id_hd
unsigned long flags;
};
-class mfm_harddisk_device : public device_t
+class mfm_harddisk_legacy_device : public device_t
{
public:
- mfm_harddisk_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+ mfm_harddisk_legacy_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
void read_sector(int cylinder, int head, int sector, UINT8 *buf);
void write_sector(int cylinder, int head, int sector, UINT8 *buf);
@@ -52,9 +106,9 @@ public:
int get_track_length();
protected:
- virtual void device_start();
- virtual void device_reset();
- virtual machine_config_constructor device_mconfig_additions() const;
+ void device_start();
+ void device_reset();
+ machine_config_constructor device_mconfig_additions() const;
private:
int find_block(const UINT8 *buffer, int start, int stop, UINT8 byte, size_t number);
@@ -70,10 +124,10 @@ private:
harddisk_image_device *m_drive;
};
-class ide_harddisk_device : public device_t
+class ide_harddisk_legacy_device : public device_t
{
public:
- ide_harddisk_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+ ide_harddisk_legacy_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
protected:
virtual void device_start() { };
virtual void device_reset() { };
@@ -81,8 +135,8 @@ protected:
};
#define MCFG_MFMHD_3_DRIVES_ADD() \
- MCFG_DEVICE_ADD(MFMHD_0, TI99_MFMHD, 0) \
- MCFG_DEVICE_ADD(MFMHD_1, TI99_MFMHD, 0) \
- MCFG_DEVICE_ADD(MFMHD_2, TI99_MFMHD, 0)
+ MCFG_DEVICE_ADD(MFMHD_0, TI99_MFMHD_LEG, 0) \
+ MCFG_DEVICE_ADD(MFMHD_1, TI99_MFMHD_LEG, 0) \
+ MCFG_DEVICE_ADD(MFMHD_2, TI99_MFMHD_LEG, 0)
#endif