mirror of
https://github.com/holub/mame
synced 2025-06-30 16:00:01 +03:00
ti99: ST225 emulation
This commit is contained in:
parent
0aebc8e54e
commit
1ad65b58ff
@ -11,7 +11,7 @@
|
|||||||
#include "emu.h"
|
#include "emu.h"
|
||||||
#include "emuopts.h"
|
#include "emuopts.h"
|
||||||
#include "audit.h"
|
#include "audit.h"
|
||||||
#include "harddisk.h"
|
#include "chd.h"
|
||||||
#include "sound/samples.h"
|
#include "sound/samples.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -74,12 +74,12 @@
|
|||||||
#define CLK_ADDR 0x0fe0
|
#define CLK_ADDR 0x0fe0
|
||||||
#define RAM_ADDR 0x1000
|
#define RAM_ADDR 0x1000
|
||||||
|
|
||||||
#define TRACE_EMU 0
|
#define TRACE_EMU 1
|
||||||
#define TRACE_CRU 0
|
#define TRACE_CRU 0
|
||||||
#define TRACE_COMP 0
|
#define TRACE_COMP 0
|
||||||
#define TRACE_RAM 0
|
#define TRACE_RAM 0
|
||||||
#define TRACE_ROM 0
|
#define TRACE_ROM 0
|
||||||
#define TRACE_LINES 0
|
#define TRACE_LINES 1
|
||||||
#define TRACE_MOTOR 0
|
#define TRACE_MOTOR 0
|
||||||
#define TRACE_DMA 0
|
#define TRACE_DMA 0
|
||||||
#define TRACE_INT 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)
|
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);
|
// 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));
|
set_bits(m_status_latch, HDC_DS_INDEX, (state==ASSERT_LINE));
|
||||||
signal_drive_status();
|
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)
|
void myarc_hfdc_device::set_bits(UINT8& byte, int mask, bool set)
|
||||||
{
|
{
|
||||||
if (set) byte |= mask;
|
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.
|
Maps the set bit to an index. The rightmost 1 bit is significant. When no
|
||||||
Returns -1 for value=0
|
bit is set, returns -1.
|
||||||
*/
|
*/
|
||||||
int myarc_hfdc_device::slog2(int value)
|
int myarc_hfdc_device::bit_to_index(int value)
|
||||||
{
|
{
|
||||||
int i=-1;
|
if (value & 0x01) return 0;
|
||||||
while (value!=0)
|
if (value & 0x02) return 1;
|
||||||
{
|
if (value & 0x04) return 2;
|
||||||
value >>= 1;
|
if (value & 0x08) return 3;
|
||||||
i++;
|
return -1;
|
||||||
}
|
|
||||||
return i;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -554,7 +572,19 @@ void myarc_hfdc_device::signal_drive_status()
|
|||||||
|
|
||||||
// Check for TRK00*
|
// Check for TRK00*
|
||||||
if ((m_current_floppy != NULL) && (!m_current_floppy->trk00_r()))
|
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
|
// 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;
|
m_output1_latch = data;
|
||||||
|
|
||||||
if ((data & 0x10) != 0)
|
if ((data & 0x10) != 0) connect_floppy_unit(bit_to_index(data & 0x0f)); // Floppy selected
|
||||||
{
|
|
||||||
// Floppy selected
|
|
||||||
connect_floppy_unit(slog2(data & 0x0f));
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
index = slog2((data>>4) & 0x0f);
|
index = bit_to_index((data>>4) & 0x0f);
|
||||||
if (index == -1)
|
|
||||||
{
|
if (index > 0) connect_harddisk_unit(index-1); // HD selected; index >= 1
|
||||||
if (TRACE_LINES) logerror("%s: Unselect all HD drives\n", tag());
|
else
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
|
disconnect_floppy_drives();
|
||||||
|
disconnect_hard_drives();
|
||||||
|
|
||||||
|
// Turn off READY and SEEK COMPLETE
|
||||||
set_bits(m_status_latch, HDC_DS_READY | HDC_DS_SKCOM, false);
|
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->dir_w((data & 0x20)==0);
|
||||||
m_current_floppy->stp_w((data & 0x10)==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
|
// We are pushing the drive status after OUTPUT2
|
||||||
signal_drive_status();
|
signal_drive_status();
|
||||||
@ -659,52 +687,74 @@ enum
|
|||||||
void myarc_hfdc_device::connect_floppy_unit(int index)
|
void myarc_hfdc_device::connect_floppy_unit(int index)
|
||||||
{
|
{
|
||||||
// Check if we have a new floppy
|
// 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)
|
disconnect_floppy_drives();
|
||||||
{
|
if (TRACE_LINES) logerror("%s: Select floppy drive DSK%d\n", tag(), index+1);
|
||||||
if (TRACE_LINES) logerror("%s: Select floppy drive DSK%d\n", tag(), index+1);
|
|
||||||
if (m_current_floppy != NULL)
|
// Connect new drive
|
||||||
{
|
m_current_floppy = m_floppy_unit[index];
|
||||||
// Disconnect old drive from index line
|
|
||||||
if (TRACE_LINES) logerror("%s: Disconnect previous index callback DSK%d\n", tag(), index+1);
|
// We don't use the READY line of floppy drives.
|
||||||
m_current_floppy->setup_index_pulse_cb(floppy_image_device::index_pulse_cb());
|
// READY is asserted when DSKx = 1
|
||||||
}
|
// The controller fetches the state with the auxbus access
|
||||||
// Connect new drive
|
if (TRACE_LINES) logerror("%s: Connect index callback DSK%d\n", tag(), index+1);
|
||||||
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
|
|
||||||
if (m_current_floppy != NULL)
|
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));
|
||||||
m_current_floppy->setup_index_pulse_cb(floppy_image_device::index_pulse_cb());
|
else
|
||||||
m_current_floppy = NULL;
|
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)
|
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;
|
m_current_harddisk = NULL;
|
||||||
// }
|
}
|
||||||
// signal_drive_status();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -836,26 +886,45 @@ void myarc_hfdc_device::device_reset()
|
|||||||
for (int i=0; i < 4; i++)
|
for (int i=0; i < 4; i++)
|
||||||
{
|
{
|
||||||
if (m_floppy_unit[i] != NULL)
|
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
|
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
|
// Disconnect all units
|
||||||
connect_floppy_unit(-1);
|
disconnect_floppy_drives();
|
||||||
connect_harddisk_unit(-1);
|
disconnect_hard_drives();
|
||||||
}
|
}
|
||||||
|
|
||||||
void myarc_hfdc_device::device_config_complete()
|
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_floppy_unit[i] = NULL;
|
||||||
|
m_harddisk_unit[i] = NULL;
|
||||||
|
}
|
||||||
|
m_floppy_unit[3] = NULL;
|
||||||
|
|
||||||
// Seems to be null when doing a "-listslots"
|
// 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)
|
||||||
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());
|
m_floppy_unit[0] = static_cast<floppy_connector*>(subdevice("f1"))->get_device();
|
||||||
if (subdevice("f3")!=NULL) m_floppy_unit[3] = static_cast<floppy_image_device*>(subdevice("f3")->first_subdevice());
|
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( "35hd", FLOPPY_35_HD ) // 80 tracks 1.4 MiB
|
||||||
SLOT_INTERFACE_END
|
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 )
|
MACHINE_CONFIG_FRAGMENT( ti99_hfdc )
|
||||||
MCFG_DEVICE_ADD(FDC_TAG, HDC9234, 0)
|
MCFG_DEVICE_ADD(FDC_TAG, HDC9234, 0)
|
||||||
MCFG_HDC9234_INTRQ_CALLBACK(WRITELINE(myarc_hfdc_device, intrq_w))
|
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_IN_CALLBACK(READ8(myarc_hfdc_device, read_buffer))
|
||||||
MCFG_HDC9234_DMA_OUT_CALLBACK(WRITE8(myarc_hfdc_device, write_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("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("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_DEVICE_ADD(CLOCK_TAG, MM58274C, 0)
|
||||||
MCFG_MM58274C_MODE24(1) // 24 hour
|
MCFG_MM58274C_MODE24(1) // 24 hour
|
||||||
MCFG_MM58274C_DAY1(0) // sunday
|
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>;
|
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;
|
UINT8 state;
|
||||||
index = slog2((m_output1_latch>>4) & 0x0f)-1;
|
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();
|
state = hd->get_status();
|
||||||
|
|
||||||
if (state & MFMHD_TRACK00) reply |= DS_TRK00;
|
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_DEVICE_ADD(CLOCK_TAG, MM58274C, 0)
|
||||||
MCFG_MM58274C_MODE24(1) // 24 hour
|
MCFG_MM58274C_MODE24(1) // 24 hour
|
||||||
MCFG_MM58274C_DAY1(0) // sunday
|
MCFG_MM58274C_DAY1(0) // sunday
|
||||||
|
|
||||||
|
MCFG_MFMHD_3_DRIVES_ADD() // add hard disks
|
||||||
MACHINE_CONFIG_END
|
MACHINE_CONFIG_END
|
||||||
|
|
||||||
ROM_START( ti99_hfdc_legacy )
|
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[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_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[0] = static_cast<mfm_harddisk_legacy_device *>(subdevice(MFMHD_0));
|
||||||
m_harddisk_unit[1] = static_cast<mfm_harddisk_device *>(m_slot->get_drive(MFMHD_1));
|
m_harddisk_unit[1] = static_cast<mfm_harddisk_legacy_device *>(subdevice(MFMHD_1));
|
||||||
m_harddisk_unit[2] = static_cast<mfm_harddisk_device *>(m_slot->get_drive(MFMHD_2));
|
m_harddisk_unit[2] = static_cast<mfm_harddisk_legacy_device *>(subdevice(MFMHD_2));
|
||||||
|
|
||||||
if (ioport("HFDCDIP")->read()&0x55)
|
if (ioport("HFDCDIP")->read()&0x55)
|
||||||
ti99_set_80_track_drives(TRUE);
|
ti99_set_80_track_drives(TRUE);
|
||||||
|
@ -18,11 +18,12 @@
|
|||||||
#define __HFDC__
|
#define __HFDC__
|
||||||
|
|
||||||
#define HFDC_MAX_FLOPPY 4
|
#define HFDC_MAX_FLOPPY 4
|
||||||
#define HFDC_MAX_HARD 4
|
#define HFDC_MAX_HARD 3
|
||||||
|
|
||||||
#include "imagedev/floppy.h"
|
#include "imagedev/floppy.h"
|
||||||
#include "machine/mm58274c.h"
|
#include "machine/mm58274c.h"
|
||||||
#include "machine/hdc9234.h"
|
#include "machine/hdc9234.h"
|
||||||
|
#include "machine/ti99_hd.h"
|
||||||
|
|
||||||
extern const device_type TI99_HFDC;
|
extern const device_type TI99_HFDC;
|
||||||
|
|
||||||
@ -49,11 +50,13 @@ public:
|
|||||||
|
|
||||||
DECLARE_FLOPPY_FORMATS( floppy_formats );
|
DECLARE_FLOPPY_FORMATS( floppy_formats );
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void device_config_complete();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
|
void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
|
||||||
void device_start();
|
void device_start();
|
||||||
void device_reset();
|
void device_reset();
|
||||||
void device_config_complete();
|
|
||||||
|
|
||||||
const rom_entry *device_rom_region() const;
|
const rom_entry *device_rom_region() const;
|
||||||
machine_config_constructor device_mconfig_additions() const;
|
machine_config_constructor device_mconfig_additions() const;
|
||||||
@ -63,18 +66,24 @@ private:
|
|||||||
void debug_read(offs_t offset, UINT8* value);
|
void debug_read(offs_t offset, UINT8* value);
|
||||||
void debug_write(offs_t offset, UINT8 data);
|
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 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
|
// Operate the floppy motors
|
||||||
void set_floppy_motors_running(bool run);
|
void set_floppy_motors_running(bool run);
|
||||||
|
|
||||||
// Connect or disconnect floppy drives
|
// Connect floppy drives
|
||||||
void connect_floppy_unit(int index);
|
void connect_floppy_unit(int index);
|
||||||
|
|
||||||
// Connect or disconnect harddisk drives
|
// Connect harddisk drives
|
||||||
void connect_harddisk_unit(int index);
|
void connect_harddisk_unit(int index);
|
||||||
|
|
||||||
|
// Disconnect drives
|
||||||
|
void disconnect_floppy_drives();
|
||||||
|
void disconnect_hard_drives();
|
||||||
|
|
||||||
// Pushes the drive status to the HDC
|
// Pushes the drive status to the HDC
|
||||||
void signal_drive_status();
|
void signal_drive_status();
|
||||||
|
|
||||||
@ -90,11 +99,14 @@ private:
|
|||||||
// Link to the attached floppy drives
|
// Link to the attached floppy drives
|
||||||
floppy_image_device* m_floppy_unit[4];
|
floppy_image_device* m_floppy_unit[4];
|
||||||
|
|
||||||
|
// Link to the attached hard disks
|
||||||
|
mfm_harddisk_device* m_harddisk_unit[3];
|
||||||
|
|
||||||
// Currently selected floppy drive
|
// Currently selected floppy drive
|
||||||
floppy_image_device* m_current_floppy;
|
floppy_image_device* m_current_floppy;
|
||||||
|
|
||||||
// Currently selected hard drive
|
// 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
|
// True: Access to DIP switch settings, false: access to line states
|
||||||
bool m_see_switches;
|
bool m_see_switches;
|
||||||
@ -159,8 +171,8 @@ private:
|
|||||||
// Signal motor_on. When TRUE, makes all drives turning.
|
// Signal motor_on. When TRUE, makes all drives turning.
|
||||||
line_state m_MOTOR_ON;
|
line_state m_MOTOR_ON;
|
||||||
|
|
||||||
// Calculates a simple version of a binary logarithm
|
// Calculates the index from the bit
|
||||||
int slog2(int value);
|
int bit_to_index(int value);
|
||||||
|
|
||||||
// Utility function to set or unset bits in a byte
|
// Utility function to set or unset bits in a byte
|
||||||
void set_bits(UINT8& byte, int mask, bool set);
|
void set_bits(UINT8& byte, int mask, bool set);
|
||||||
@ -170,6 +182,26 @@ private:
|
|||||||
int m_readyflags;
|
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];
|
legacy_floppy_image_device* m_floppy_unit[HFDC_MAX_FLOPPY];
|
||||||
|
|
||||||
/* Connected harddisk drives. */
|
/* 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 */
|
/* DMA address latch */
|
||||||
UINT32 m_dma_address;
|
UINT32 m_dma_address;
|
||||||
|
@ -467,8 +467,6 @@ MACHINE_CONFIG_FRAGMENT( peribox_device )
|
|||||||
MCFG_DEVICE_ADD(FLOPPY_3, LEGACY_FLOPPY, 0)
|
MCFG_DEVICE_ADD(FLOPPY_3, LEGACY_FLOPPY, 0)
|
||||||
MCFG_DEVICE_CONFIG(ti99_4_floppy_interface)
|
MCFG_DEVICE_CONFIG(ti99_4_floppy_interface)
|
||||||
MCFG_LEGACY_FLOPPY_IDX_CB(WRITELINE(peribox_device, indexhole))
|
MCFG_LEGACY_FLOPPY_IDX_CB(WRITELINE(peribox_device, indexhole))
|
||||||
|
|
||||||
MCFG_MFMHD_3_DRIVES_ADD()
|
|
||||||
MACHINE_CONFIG_END
|
MACHINE_CONFIG_END
|
||||||
|
|
||||||
machine_config_constructor peribox_device::device_mconfig_additions() const
|
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_ADD(FLOPPY_3, LEGACY_FLOPPY, 0)
|
||||||
MCFG_DEVICE_CONFIG(ti99_4_floppy_interface)
|
MCFG_DEVICE_CONFIG(ti99_4_floppy_interface)
|
||||||
MCFG_LEGACY_FLOPPY_IDX_CB(WRITELINE(peribox_device, indexhole))
|
MCFG_LEGACY_FLOPPY_IDX_CB(WRITELINE(peribox_device, indexhole))
|
||||||
MCFG_MFMHD_3_DRIVES_ADD()
|
|
||||||
MACHINE_CONFIG_END
|
MACHINE_CONFIG_END
|
||||||
|
|
||||||
machine_config_constructor peribox_gen_device::device_mconfig_additions() const
|
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_ADD(FLOPPY_3, LEGACY_FLOPPY, 0)
|
||||||
MCFG_DEVICE_CONFIG(ti99_4_floppy_interface)
|
MCFG_DEVICE_CONFIG(ti99_4_floppy_interface)
|
||||||
MCFG_LEGACY_FLOPPY_IDX_CB(WRITELINE(peribox_device, indexhole))
|
MCFG_LEGACY_FLOPPY_IDX_CB(WRITELINE(peribox_device, indexhole))
|
||||||
MCFG_MFMHD_3_DRIVES_ADD()
|
|
||||||
MACHINE_CONFIG_END
|
MACHINE_CONFIG_END
|
||||||
|
|
||||||
machine_config_constructor peribox_998_device::device_mconfig_additions() const
|
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_ADD(FLOPPY_3, LEGACY_FLOPPY, 0)
|
||||||
MCFG_DEVICE_CONFIG(ti99_4_floppy_interface)
|
MCFG_DEVICE_CONFIG(ti99_4_floppy_interface)
|
||||||
MCFG_LEGACY_FLOPPY_IDX_CB(WRITELINE(peribox_device, indexhole))
|
MCFG_LEGACY_FLOPPY_IDX_CB(WRITELINE(peribox_device, indexhole))
|
||||||
MCFG_MFMHD_3_DRIVES_ADD()
|
|
||||||
MACHINE_CONFIG_END
|
MACHINE_CONFIG_END
|
||||||
|
|
||||||
machine_config_constructor peribox_sg_device::device_mconfig_additions() const
|
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 );
|
return MACHINE_CONFIG_NAME( peribox_sg_device );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
Another variant of the box; used for the TI with EVPC. The EVPC is
|
Another variant of the box; used for the TI with EVPC. The EVPC is
|
||||||
obviously required.
|
obviously required.
|
||||||
@ -684,7 +678,6 @@ MACHINE_CONFIG_FRAGMENT( peribox_ev_device )
|
|||||||
MCFG_DEVICE_ADD(FLOPPY_3, LEGACY_FLOPPY, 0)
|
MCFG_DEVICE_ADD(FLOPPY_3, LEGACY_FLOPPY, 0)
|
||||||
MCFG_DEVICE_CONFIG(ti99_4_floppy_interface)
|
MCFG_DEVICE_CONFIG(ti99_4_floppy_interface)
|
||||||
MCFG_LEGACY_FLOPPY_IDX_CB(WRITELINE(peribox_device, indexhole))
|
MCFG_LEGACY_FLOPPY_IDX_CB(WRITELINE(peribox_device, indexhole))
|
||||||
MCFG_MFMHD_3_DRIVES_ADD()
|
|
||||||
MACHINE_CONFIG_END
|
MACHINE_CONFIG_END
|
||||||
|
|
||||||
machine_config_constructor peribox_ev_device::device_mconfig_additions() const
|
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
|
// harddisk_image_device - destructor
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
@ -51,6 +51,8 @@ public:
|
|||||||
chd_file *get_chd_file();
|
chd_file *get_chd_file();
|
||||||
|
|
||||||
protected:
|
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
|
// device-level overrides
|
||||||
virtual void device_config_complete();
|
virtual void device_config_complete();
|
||||||
virtual void device_start();
|
virtual void device_start();
|
||||||
|
@ -24,37 +24,37 @@
|
|||||||
#include "hdc9234.h"
|
#include "hdc9234.h"
|
||||||
|
|
||||||
// Per-command debugging
|
// Per-command debugging
|
||||||
#define TRACE_SELECT 0
|
#define TRACE_SELECT 1
|
||||||
#define TRACE_STEP 0
|
#define TRACE_STEP 1
|
||||||
#define TRACE_RESTORE 0
|
#define TRACE_RESTORE 1
|
||||||
#define TRACE_SUBSTATES 0
|
#define TRACE_SUBSTATES 1
|
||||||
#define TRACE_READ 0
|
#define TRACE_READ 1
|
||||||
#define TRACE_WRITE 0
|
#define TRACE_WRITE 1
|
||||||
#define TRACE_READREG 0
|
#define TRACE_READREG 1
|
||||||
#define TRACE_SETREG 0
|
#define TRACE_SETREG 1
|
||||||
#define TRACE_SETPTR 0
|
#define TRACE_SETPTR 1
|
||||||
#define TRACE_FORMAT 0
|
#define TRACE_FORMAT 1
|
||||||
#define TRACE_READTRACK 0
|
#define TRACE_READTRACK 1
|
||||||
|
|
||||||
// Common states
|
// Common states
|
||||||
#define TRACE_READID 0
|
#define TRACE_READID 1
|
||||||
#define TRACE_VERIFY 0
|
#define TRACE_VERIFY 1
|
||||||
#define TRACE_TRANSFER 0
|
#define TRACE_TRANSFER 1
|
||||||
|
|
||||||
// Live states debugging
|
// Live states debugging
|
||||||
#define TRACE_LIVE 0
|
#define TRACE_LIVE 1
|
||||||
#define TRACE_SHIFT 0
|
#define TRACE_SHIFT 1
|
||||||
#define TRACE_SYNC 0
|
#define TRACE_SYNC 1
|
||||||
|
|
||||||
// Misc debugging
|
// Misc debugging
|
||||||
#define TRACE_DELAY 0
|
#define TRACE_DELAY 0
|
||||||
#define TRACE_INT 0
|
#define TRACE_INT 1
|
||||||
#define TRACE_LINES 0
|
#define TRACE_LINES 1
|
||||||
#define TRACE_INDEX 0
|
#define TRACE_INDEX 1
|
||||||
#define TRACE_DMA 0
|
#define TRACE_DMA 1
|
||||||
#define TRACE_DONE 0
|
#define TRACE_DONE 1
|
||||||
#define TRACE_FAIL 0
|
#define TRACE_FAIL 1
|
||||||
#define TRACE_AUXBUS 0
|
#define TRACE_AUXBUS 1
|
||||||
|
|
||||||
#define TRACE_DETAIL 0
|
#define TRACE_DETAIL 0
|
||||||
|
|
||||||
@ -239,8 +239,8 @@ enum
|
|||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
GEN_TIMER = 1,
|
GEN_TIMER = 1,
|
||||||
COM_TIMER,
|
COM_TIMER /*,
|
||||||
LIVE_TIMER
|
LIVE_TIMER */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1027,6 +1027,7 @@ void hdc9234_device::drive_deselect()
|
|||||||
{
|
{
|
||||||
if (TRACE_SELECT) logerror("%s: DESELECT command\n", tag());
|
if (TRACE_SELECT) logerror("%s: DESELECT command\n", tag());
|
||||||
m_selected_drive_number = NODRIVE;
|
m_selected_drive_number = NODRIVE;
|
||||||
|
m_output1 = 0x00;
|
||||||
set_command_done(TC_SUCCESS);
|
set_command_done(TC_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1066,7 +1067,7 @@ void hdc9234_device::restore_drive()
|
|||||||
// Track 0 has not been reached yet
|
// Track 0 has not been reached yet
|
||||||
if ((m_register_r[DRIVE_STATUS] & HDC_DS_READY)==0)
|
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
|
// 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
|
// that if a drive is not connected we do not want an error message
|
||||||
cont = SUCCESS;
|
cont = SUCCESS;
|
||||||
@ -1081,6 +1082,7 @@ void hdc9234_device::restore_drive()
|
|||||||
// When we have buffered steps, the seek limit will be reached
|
// When we have buffered steps, the seek limit will be reached
|
||||||
// before TRK00 is asserted. In that case we have to wait for
|
// before TRK00 is asserted. In that case we have to wait for
|
||||||
// SEEK_COMPLETE. We also wait as soon as TRK00 is asserted.
|
// 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);
|
wait_line(SEEKCOMP_LINE, ASSERT_LINE, SEEK_COMPLETE, false);
|
||||||
cont = WAIT;
|
cont = WAIT;
|
||||||
}
|
}
|
||||||
@ -1809,7 +1811,8 @@ void hdc9234_device::live_start(int state)
|
|||||||
|
|
||||||
void hdc9234_device::live_run()
|
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.
|
the requested data are read.
|
||||||
limit: if unlimited (attotime::never), run up to the end of the track and wait there
|
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
|
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)
|
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;
|
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.
|
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.
|
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();
|
m_output2 = (m_output2 & 0xb0) | desired_head();
|
||||||
if (m_reduced_write_current) m_output2 |= OUT2_REDWRT;
|
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)
|
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;
|
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
|
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
|
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:
|
case COM_TIMER:
|
||||||
process_command();
|
process_command();
|
||||||
break;
|
break;
|
||||||
case LIVE_TIMER:
|
/* case LIVE_TIMER:
|
||||||
live_run();
|
live_run();
|
||||||
break;
|
break; */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3393,7 +3440,7 @@ void hdc9234_device::device_start()
|
|||||||
// allocate timers
|
// allocate timers
|
||||||
m_timer = timer_alloc(GEN_TIMER);
|
m_timer = timer_alloc(GEN_TIMER);
|
||||||
m_cmd_timer = timer_alloc(COM_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;
|
m_live_state.state = IDLE;
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "emu.h"
|
#include "emu.h"
|
||||||
#include "imagedev/floppy.h"
|
#include "imagedev/floppy.h"
|
||||||
#include "fdc_pll.h"
|
#include "fdc_pll.h"
|
||||||
|
#include "ti99_hd.h"
|
||||||
|
|
||||||
extern const device_type HDC9234;
|
extern const device_type HDC9234;
|
||||||
|
|
||||||
@ -109,6 +110,9 @@ public:
|
|||||||
// is changed outside of the controller, and by this way we let it know.
|
// is changed outside of the controller, and by this way we let it know.
|
||||||
void connect_floppy_drive(floppy_image_device *floppy);
|
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:
|
protected:
|
||||||
void device_start();
|
void device_start();
|
||||||
void device_reset();
|
void device_reset();
|
||||||
@ -134,6 +138,9 @@ private:
|
|||||||
// Currently connected floppy
|
// Currently connected floppy
|
||||||
floppy_image_device* m_floppy;
|
floppy_image_device* m_floppy;
|
||||||
|
|
||||||
|
// Currently connected harddisk
|
||||||
|
mfm_harddisk_device* m_harddisk;
|
||||||
|
|
||||||
// internal register OUTPUT1
|
// internal register OUTPUT1
|
||||||
UINT8 m_output1, m_output1_old;
|
UINT8 m_output1, m_output1_old;
|
||||||
|
|
||||||
@ -220,6 +227,9 @@ private:
|
|||||||
|
|
||||||
// Analyses the track until the given time
|
// Analyses the track until the given time
|
||||||
void live_run_until(attotime limit);
|
void live_run_until(attotime limit);
|
||||||
|
|
||||||
|
// Same for hard disks
|
||||||
|
void live_run_hd_until(attotime limit);
|
||||||
|
|
||||||
// Live run until next index pulse
|
// Live run until next index pulse
|
||||||
void live_run();
|
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());
|
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;
|
m_harddisk = drive;
|
||||||
if (VERBOSE>3)
|
if (VERBOSE>3)
|
||||||
|
@ -99,7 +99,7 @@ public:
|
|||||||
// Used to reconfigure the drive connections. Drive selection is done
|
// Used to reconfigure the drive connections. Drive selection is done
|
||||||
// using the select lines and maybe also the user-programmable outputs.
|
// using the select lines and maybe also the user-programmable outputs.
|
||||||
void connect_floppy_drive(legacy_floppy_image_device *drive);
|
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();
|
void reset();
|
||||||
|
|
||||||
@ -223,7 +223,7 @@ private:
|
|||||||
// We expect the embedding board to replace the drive according to the
|
// We expect the embedding board to replace the drive according to the
|
||||||
// select lines.
|
// select lines.
|
||||||
legacy_floppy_image_device *m_drive;
|
legacy_floppy_image_device *m_drive;
|
||||||
mfm_harddisk_device *m_harddisk;
|
mfm_harddisk_legacy_device *m_harddisk;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -2,23 +2,21 @@
|
|||||||
// copyright-holders:Michael Zapf
|
// copyright-holders:Michael Zapf
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
|
|
||||||
Hard disk support
|
Hard disk emulation
|
||||||
|
|
||||||
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"
|
|
||||||
|
|
||||||
Michael Zapf
|
Michael Zapf
|
||||||
April 2010
|
April 2010
|
||||||
February 2012: Rewritten as class
|
February 2012: Rewritten as class
|
||||||
|
April 2015: Rewritten with deeper emulation detail
|
||||||
|
|
||||||
|
References:
|
||||||
|
[1] ST225 OEM Manual, Seagate
|
||||||
|
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#include "emu.h"
|
#include "emu.h"
|
||||||
#include "formats/imageutl.h"
|
#include "formats/imageutl.h"
|
||||||
#include "harddisk.h"
|
#include "harddisk.h"
|
||||||
#include "smc92x4.h"
|
|
||||||
|
|
||||||
#include "ti99_hd.h"
|
#include "ti99_hd.h"
|
||||||
|
|
||||||
@ -33,8 +31,211 @@
|
|||||||
#define GAP4 340
|
#define GAP4 340
|
||||||
#define SYNC 13
|
#define SYNC 13
|
||||||
|
|
||||||
mfm_harddisk_device::mfm_harddisk_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
enum
|
||||||
: device_t(mconfig, TI99_MFMHD, "MFM Harddisk", tag, owner, clock, "mfm_harddisk", __FILE__)
|
{
|
||||||
|
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
|
define idents beyond cylinder 1023, but formatting programs seem to
|
||||||
continue with 0xfd for cylinders between 1024 and 2047.
|
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 < 256) return 0xfe;
|
||||||
if (cylinder < 512) return 0xff;
|
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.
|
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;
|
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 */
|
/* 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;
|
UINT32 lba;
|
||||||
if (VERBOSE>5) LOG("ti99_hd: read_sector(%d, %d, %d)\n", cylinder, head, sector);
|
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;
|
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;
|
UINT32 lba;
|
||||||
if (VERBOSE>5) LOG("ti99_hd: write_sector(%d, %d, %d)\n", cylinder, head, sector);
|
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
|
Searches a block containing number * byte, starting at the given
|
||||||
position. Returns the position of the first byte of the block.
|
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;
|
int i = start;
|
||||||
size_t current = number;
|
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;
|
return TI99HD_BLOCKNOTFOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mfm_harddisk_device::get_track_length()
|
int mfm_harddisk_legacy_device::get_track_length()
|
||||||
{
|
{
|
||||||
int count;
|
int count;
|
||||||
int size;
|
int size;
|
||||||
@ -187,7 +388,7 @@ int mfm_harddisk_device::get_track_length()
|
|||||||
WARNING: This function is untested! We need to create a suitable
|
WARNING: This function is untested! We need to create a suitable
|
||||||
application program for the TI which makes use of it.
|
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. */
|
/* We assume an interleave of 3 for 32 sectors. */
|
||||||
int step = 3;
|
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.
|
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.
|
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;
|
int current_pos = 0;
|
||||||
bool found;
|
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;
|
UINT8 status = 0;
|
||||||
hard_disk_file *file = m_drive->get_hard_disk_file();
|
hard_disk_file *file = m_drive->get_hard_disk_file();
|
||||||
@ -422,7 +623,7 @@ UINT8 mfm_harddisk_device::get_status()
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mfm_harddisk_device::seek(int direction)
|
void mfm_harddisk_legacy_device::seek(int direction)
|
||||||
{
|
{
|
||||||
const hard_disk_info *info;
|
const hard_disk_info *info;
|
||||||
hard_disk_file *file = m_drive->get_hard_disk_file();
|
hard_disk_file *file = m_drive->get_hard_disk_file();
|
||||||
@ -449,7 +650,7 @@ void mfm_harddisk_device::seek(int direction)
|
|||||||
m_seeking = false;
|
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;
|
const hard_disk_info *info;
|
||||||
hard_disk_file *file;
|
hard_disk_file *file;
|
||||||
@ -479,13 +680,13 @@ void mfm_harddisk_device::get_next_id(int head, chrn_id_hd *id)
|
|||||||
id->flags = 0;
|
id->flags = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mfm_harddisk_device::device_start()
|
void mfm_harddisk_legacy_device::device_start()
|
||||||
{
|
{
|
||||||
m_current_cylinder = 0;
|
m_current_cylinder = 0;
|
||||||
m_current_head = 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_drive = static_cast<harddisk_image_device *>(subdevice("drive"));
|
||||||
m_seeking = false;
|
m_seeking = false;
|
||||||
@ -497,9 +698,9 @@ MACHINE_CONFIG_FRAGMENT( mfmhd )
|
|||||||
MCFG_HARDDISK_ADD("drive")
|
MCFG_HARDDISK_ADD("drive")
|
||||||
MACHINE_CONFIG_END
|
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 );
|
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 "emu.h"
|
||||||
#include "imagedev/harddriv.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_0 "mfmhd0"
|
||||||
#define MFMHD_1 "mfmhd1"
|
#define MFMHD_1 "mfmhd1"
|
||||||
#define MFMHD_2 "mfmhd2"
|
#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
|
Needed to adapt to higher cylinder numbers. Floppies do not have such
|
||||||
@ -37,10 +91,10 @@ struct chrn_id_hd
|
|||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
class mfm_harddisk_device : public device_t
|
class mfm_harddisk_legacy_device : public device_t
|
||||||
{
|
{
|
||||||
public:
|
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 read_sector(int cylinder, int head, int sector, UINT8 *buf);
|
||||||
void write_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();
|
int get_track_length();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void device_start();
|
void device_start();
|
||||||
virtual void device_reset();
|
void device_reset();
|
||||||
virtual machine_config_constructor device_mconfig_additions() const;
|
machine_config_constructor device_mconfig_additions() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int find_block(const UINT8 *buffer, int start, int stop, UINT8 byte, size_t number);
|
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;
|
harddisk_image_device *m_drive;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ide_harddisk_device : public device_t
|
class ide_harddisk_legacy_device : public device_t
|
||||||
{
|
{
|
||||||
public:
|
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:
|
protected:
|
||||||
virtual void device_start() { };
|
virtual void device_start() { };
|
||||||
virtual void device_reset() { };
|
virtual void device_reset() { };
|
||||||
@ -81,8 +135,8 @@ protected:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#define MCFG_MFMHD_3_DRIVES_ADD() \
|
#define MCFG_MFMHD_3_DRIVES_ADD() \
|
||||||
MCFG_DEVICE_ADD(MFMHD_0, TI99_MFMHD, 0) \
|
MCFG_DEVICE_ADD(MFMHD_0, TI99_MFMHD_LEG, 0) \
|
||||||
MCFG_DEVICE_ADD(MFMHD_1, TI99_MFMHD, 0) \
|
MCFG_DEVICE_ADD(MFMHD_1, TI99_MFMHD_LEG, 0) \
|
||||||
MCFG_DEVICE_ADD(MFMHD_2, TI99_MFMHD, 0)
|
MCFG_DEVICE_ADD(MFMHD_2, TI99_MFMHD_LEG, 0)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user