From 1ad65b58ff532505885794cc9ac7e9693deb57dc Mon Sep 17 00:00:00 2001 From: Michael Zapf Date: Sun, 19 Apr 2015 23:09:05 +0200 Subject: [PATCH] ti99: ST225 emulation --- src/emu/audit.c | 2 +- src/emu/bus/ti99_peb/hfdc.c | 274 ++++++++++++++++++++++----------- src/emu/bus/ti99_peb/hfdc.h | 52 +++++-- src/emu/bus/ti99_peb/peribox.c | 7 - src/emu/imagedev/harddriv.c | 14 ++ src/emu/imagedev/harddriv.h | 2 + src/emu/machine/hdc9234.c | 111 +++++++++---- src/emu/machine/hdc9234.h | 10 ++ src/emu/machine/smc92x4.c | 2 +- src/emu/machine/smc92x4.h | 4 +- src/emu/machine/ti99_hd.c | 249 +++++++++++++++++++++++++++--- src/emu/machine/ti99_hd.h | 76 +++++++-- 12 files changed, 629 insertions(+), 174 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]); - } - } - else - { - if (TRACE_LINES) logerror("%s: Unselect all floppy drives\n", tag()); - // Disconnect current floppy + 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()); - 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]); } - // 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_hard_drives(); } void myarc_hfdc_device::connect_harddisk_unit(int index) { -// if (index < 0) -// { + if (m_harddisk_unit[index] != m_current_harddisk) + { + 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_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); + } + + // We can only run a floppy or a harddisk at a time, not both + disconnect_floppy_drives(); +} + +void myarc_hfdc_device::disconnect_floppy_drives() +{ + 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: Connector %d has no floppy attached\n", tag(), i); + 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: 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(subdevice("f0")->first_subdevice()); - if (subdevice("f1")!=NULL) m_floppy_unit[1] = static_cast(subdevice("f1")->first_subdevice()); - if (subdevice("f2")!=NULL) m_floppy_unit[2] = static_cast(subdevice("f2")->first_subdevice()); - if (subdevice("f3")!=NULL) m_floppy_unit[3] = static_cast(subdevice("f3")->first_subdevice()); + if (subdevice("f1")!=NULL) + { + m_floppy_unit[0] = static_cast(subdevice("f1"))->get_device(); + m_floppy_unit[1] = static_cast(subdevice("f2"))->get_device(); + m_floppy_unit[2] = static_cast(subdevice("f3"))->get_device(); + m_floppy_unit[3] = static_cast(subdevice("f4"))->get_device(); + + m_harddisk_unit[0] = static_cast(subdevice("h1"))->get_device(); + m_harddisk_unit[1] = static_cast(subdevice("h2"))->get_device(); + m_harddisk_unit[2] = static_cast(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; +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(get_card_device()); +} + +void mfm_harddisk_connector::device_start() +{ +} + +const device_type MFM_HD_CONNECTOR = &device_creator; + // ========================================================================= /* @@ -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(m_slot->get_drive(FLOPPY_2)); m_floppy_unit[3] = static_cast(m_slot->get_drive(FLOPPY_3)); - m_harddisk_unit[0] = static_cast(m_slot->get_drive(MFMHD_0)); - m_harddisk_unit[1] = static_cast(m_slot->get_drive(MFMHD_1)); - m_harddisk_unit[2] = static_cast(m_slot->get_drive(MFMHD_2)); + m_harddisk_unit[0] = static_cast(subdevice(MFMHD_0)); + m_harddisk_unit[1] = static_cast(subdevice(MFMHD_1)); + m_harddisk_unit[2] = static_cast(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 @@ -47,6 +47,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) { @@ -2622,6 +2627,40 @@ void hdc9234_device::live_run_until(attotime limit) m_last_live_state = UNDEF; } +/* + 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. @@ -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) { @@ -3337,6 +3376,14 @@ void hdc9234_device::connect_floppy_drive(floppy_image_device* floppy) m_floppy = 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 @@ -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; + +// =========================================================================== +// 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(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; +const device_type TI99_MFMHD_LEG = &device_creator; 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 index_pulse_cb; + typedef delegate 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