mirror of
https://github.com/holub/mame
synced 2025-04-22 08:22:15 +03:00
ti99: ST225 emulation
This commit is contained in:
parent
0aebc8e54e
commit
1ad65b58ff
@ -11,7 +11,7 @@
|
||||
#include "emu.h"
|
||||
#include "emuopts.h"
|
||||
#include "audit.h"
|
||||
#include "harddisk.h"
|
||||
#include "chd.h"
|
||||
#include "sound/samples.h"
|
||||
|
||||
|
||||
|
@ -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<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);
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
//-------------------------------------------------
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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>;
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user