(MESS) Changing to new floppy implementation, part 1.

This commit is contained in:
Michael Zapf 2014-02-12 12:41:40 +00:00
parent c9be000d5c
commit fb9183eb2c
5 changed files with 785 additions and 47 deletions

View File

@ -74,6 +74,7 @@
* always be done.
********************************************************************/
#include "emu.h"
#include <string.h>
#include <assert.h>
#include <time.h>
@ -81,9 +82,231 @@
#include "imageutl.h"
#include "ti99_dsk.h"
/*
New format implementation. See below for legacy implementation.
*/
const char *ti99_sdf_format::name() const
{
return "sdf";
}
const char *ti99_sdf_format::description() const
{
return "TI99 sector dump floppy disk image";
}
const char *ti99_sdf_format::extensions() const
{
return "dsk";
}
bool ti99_sdf_format::supports_save() const
{
return true;
}
int ti99_sdf_format::identify(io_generic *io, UINT32 form_factor)
{
UINT64 file_size = io_generic_size(io);
// Adding support for another sector image format which adds 768 bytes
// as a bad sector map
if ((file_size / 256) % 10 == 3)
{
logerror("Stripping map of bad sectors at image end\n");
file_size -= 768;
}
// Formats with 9 sectors per track
if (((file_size % 92160)==0)
&& ( (file_size/92160==1)
|| (file_size/92160==2)
|| (file_size/92160==4)
|| (file_size/92160==8)
|| (file_size/92160==16))) return 100;
// Formats with 16 sectors per track (rare)
if (((file_size % 163840)==0)
&& ( (file_size/163840==1)
|| (file_size/163840==2))) return 100;
logerror("Unrecognized disk image geometry\n");
return 0;
}
int ti99_sdf_format::find_size(io_generic *io, UINT32 form_factor)
{
UINT64 file_size = io_generic_size(io);
// See above
if ((file_size / 256) % 10 == 3) file_size -= 768;
for (int i=0; formats[i].form_factor != 0; i++)
{
logerror("ti99_dsk: trying size=%d, sec=%d, tr=%d, head=%d, ss=%d\n", (int)file_size, formats[i].sector_count, formats[i].track_count, formats[i].head_count, formats[i].sector_base_size);
if (formats[i].sector_count * formats[i].track_count * formats[i].head_count * formats[i].sector_base_size == (int)file_size)
{
logerror("ti99_dsk: format %d matches\n", i);
return i;
}
}
return -1;
}
int ti99_sdf_format::get_image_offset(const format &f, int head, int track)
{
// Note that the logical track arrangement on TI disks is
//
// 00 01 02 03 ... 38 39 side 0
// 79 78 77 76 ... 41 40 side 1
//
// and that the SDF format stores the tracks in logical order
// 00 01 02 03 ... 38 39 [40 41 ... 79]
//
int logicaltrack = head * f.track_count;
logicaltrack += ((head&1)==0)? track : (f.track_count - 1 - track);
logerror("ti99_dsk: track %d, head %d -> logical track %d\n", track, head, logicaltrack);
return logicaltrack * compute_track_size(f);
}
/*
* Common formats:
* 90 KiB = 40 tracks / 1 side / 9 sectors = SSSD
* 180 KiB = 40 tracks / 2 side / 9 sectors = DSSD (most common)
* = 40 tracks / 1 side / 18 sectors = SSDD (rare)
* = 80 tracks / 1 side / 9 sectors = SSSD80 (rare)
* 360 KiB = 40 tracks / 2 side / 18 sectors = DSDD (most common)
* = 80 tracks / 2 side / 9 sectors = DSSD80 (rare)
* = 80 tracks / 1 side / 18 sectors = SSDD80 (rare)
* = 40 tracks / 1 side / 36 sectors = SSHD (rare)
* 720 KiB = 80 tracks / 2 side / 18 sectors = DSDD80 (most common)
* 1440 KiB= 80 tracks / 2 side / 36 sectors = DSHD80 (most common)
*
* Moreover, there may be formats with 35 tracks (ancient) and 8 sectors/track.
* We only check for the 8 sector formats.
* 160 KiB = 40 tracks / 1 side / 16 sectors = SSDD8
* 320 KiB = 40 tracks / 2 side / 16 sectors = DSDD8
*/
/* const ti99_sdf_format::file_format ti99_sdf_format::file_formats[] =
{
{ 90, floppy_image::SSSD, 9, 40, 1, 4000 }, // 5.25, 3.5 with double-step
{ 160, floppy_image::DSSD, 8, 40, 2, 4000 }, // 5.25, 3.5 with double-step
{ 180, floppy_image::DSSD, 9, 40, 2, 4000 }, // 5.25, 3.5 with double-step
{ 180, floppy_image::SSDD, 18, 40, 2, 2000 }, // 5.25, 3.5 with double-step
{ 320, floppy_image::DSDD, 16, 40, 2, 2000 }, // 5.25, 3.5 with double-step
{ 360, floppy_image::DSDD, 18, 40, 2, 2000 }, // 5.25, 3.5 with double-step
{ 720, floppy_image::DSDD, 18, 80, 2, 2000 }, // 3.5
{ 1440, floppy_image::DSHD, 36, 80, 2, 1000 }, // 3.5
{ 0, 0, 0, 0, 0, 0 }
// Add more formats with VIB check
}; */
// Format: form_factor, variant, encoding, cell_size, sector_count, track_count,
// head_count, sector_base_size, per_sector_size, sector_base_id,
// per_sector_id, gap1, gap2, gap3
const ti99_sdf_format::format ti99_sdf_format::formats[] =
{
{ // 90K 5.25" single density single sided
floppy_image::FF_525, floppy_image::SSSD, floppy_image::FM,
4000, 9, 40, 1, 256, {}, 0, {}, 16, 11, 45
},
{ // 180K 5.25" single density double sided
floppy_image::FF_525, floppy_image::SSSD, floppy_image::FM,
4000, 9, 40, 2, 256, {}, 0, {}, 16, 11, 45
},
{ 0 }
};
/*
* FM track image
*/
floppy_image_format_t::desc_e* ti99_sdf_format::get_desc_fm(const format &f, int &current_size, int &end_gap_index)
{
static floppy_image_format_t::desc_e desc_fm[] =
{
{ SECTOR_INTERLEAVE_SKEW, 3, 3 }, // skew/2 because of track*2+head
{ FM, 0x00, f.gap_1 }, // Gap 1 (note that we have 00 instead of ff)
{ SECTOR_LOOP_START, 0, 8 }, // 9 sectors
{ FM, 0x00, 6 }, // pre-id gap
{ CRC_CCITT_FM_START, 1 },
{ RAW, 0xf57e, 1 }, // IDAM (fe, clock=c7; 11110101 01111110)
{ TRACK_ID_FM },
{ HEAD_ID_FM },
{ SECTOR_ID_FM },
{ SIZE_ID_FM },
{ CRC_END, 1 },
{ CRC, 1 },
{ FM, 0xff, f.gap_2 }, // Gap 2
{ FM, 0x00, 6 },
{ CRC_CCITT_FM_START, 2 },
{ RAW, 0xf56f, 1 }, // DAM (fb, clock=c7; 11110101 01101111)
{ SECTOR_DATA_FM, -1 }, // Sector data
{ CRC_END, 2 },
{ CRC, 2 },
{ FM, 0xff, f.gap_3 }, // Gap 3
{ SECTOR_LOOP_END },
{ FM, 0xff, 0 }, // track lead-out (end gap, 231)
{ END }
};
current_size = (f.gap_1 + 9 * (6 + 1 + 4 + 2 + f.gap_2 + 6 + 1 + 256 + 2 + f.gap_3) + 0) * 16;
end_gap_index = 21;
return desc_fm;
}
/*
* MFM track image
*/
floppy_image_format_t::desc_e* ti99_sdf_format::get_desc_mfm(const format &f, int &current_size, int &end_gap_index)
{
static floppy_image_format_t::desc_e desc_mfm[] =
{
{ SECTOR_INTERLEAVE_SKEW, 10, 0 },
{ MFM, 0x4e, 40 }, // track lead-in
{ SECTOR_LOOP_START, 0, 17 }, // 18 sectors
{ CRC_CCITT_START, 1 },
{ RAW, 0x4489, 3 }, // A1 sync mark
{ MFM, 0xfe, 1 }, // IDAM
{ TRACK_ID },
{ HEAD_ID },
{ SECTOR_ID },
{ SIZE_ID },
{ CRC_END, 1 },
{ CRC, 1 },
{ MFM, 0x4e, 22 }, // Gap 2
{ MFM, 0x00, 12 },
{ CRC_CCITT_START, 2 },
{ RAW, 0x4489, 3 }, // A1
{ MFM, 0xfb, 1 }, // DAM
{ SECTOR_DATA, -1 }, // Sector data
{ CRC_END, 2 },
{ CRC, 2 },
{ MFM, 0x4e, 24 }, // Gap 3
{ SECTOR_LOOP_END },
{ MFM, 0x4e, 0 }, // track lead-out (712)
{ END }
};
current_size = (40 + 18 * (3 + 1 + 4 + 2 + 22 + 12 + 3 + 1 + 256 + 2 + 24) + 0) * 16;
end_gap_index = 22;
return desc_mfm;
}
const floppy_format_type FLOPPY_TI99_SDF_FORMAT = &floppy_image_format_creator<ti99_sdf_format>;
//==========================================================================
#define SECTOR_SIZE 256
#define TI99_IDAM_LENGTH 7
/**************************************************************
Legacy implementation
**************************************************************/
/*
Determines whether we are using 80 track drives. This variable is
necessary unless we get information about the dip

View File

@ -11,9 +11,42 @@
#define TI99_DSK_H
#include "flopimg.h"
#include "wd177x_dsk.h"
/*
New implementation.
TDF format still to be done;
also, this implementation just considers FM for now.
*/
class ti99_sdf_format : public wd177x_format
{
public:
ti99_sdf_format(): wd177x_format(formats) { }
int identify(io_generic *io, UINT32 form_factor);
const char *name() const;
const char *description() const;
const char *extensions() const;
bool supports_save() const;
private:
static const format formats[];
floppy_image_format_t::desc_e* get_desc_fm(const format &f, int &current_size, int &end_gap_index);
floppy_image_format_t::desc_e* get_desc_mfm(const format &f, int &current_size, int &end_gap_index);
int get_format_param(io_generic *io);
int get_image_offset(const format &f, int head, int track);
int find_size(io_generic *io, UINT32 form_factor);
};
/*
Legacy implementation.
*/
LEGACY_FLOPPY_OPTIONS_EXTERN(ti99);
void ti99_set_80_track_drives(int use80);
extern const floppy_format_type FLOPPY_TI99_SDF_FORMAT;
#endif /* TI99_DSK_H */

View File

@ -418,6 +418,7 @@ SLOT_INTERFACE_START( peribox_slot7 )
SLOT_INTERFACE_END
SLOT_INTERFACE_START( peribox_slot8 )
SLOT_INTERFACE("tifdcleg", TI99_FDC_LEG)
SLOT_INTERFACE("tifdc", TI99_FDC)
SLOT_INTERFACE("bwg", TI99_BWG)
SLOT_INTERFACE("hfdc", TI99_HFDC)
@ -462,6 +463,7 @@ SLOT_INTERFACE_START( peribox_slot7nobwg )
SLOT_INTERFACE_END
SLOT_INTERFACE_START( peribox_slot8nobwg )
SLOT_INTERFACE("tifdcleg", TI99_FDC_LEG)
SLOT_INTERFACE("tifdc", TI99_FDC)
SLOT_INTERFACE("hfdc", TI99_HFDC)
SLOT_INTERFACE_END

View File

@ -42,39 +42,22 @@
#define TRACE_MOTOR 0
// ----------------------------------
#define TI_FDC_TAG "ti_dssd_controller"
#define FDC_TAG "wd1771"
#define FDC_TAG "fd1771"
#define MOTOR_TIMER 1
const wd17xx_interface ti_wd17xx_interface =
{
DEVCB_NULL,
DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER, ti_fdc_device, intrq_w),
DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER, ti_fdc_device, drq_w),
{ PFLOPPY_0, PFLOPPY_1, PFLOPPY_2, NULL }
};
#define TI_FDC_TAG "ti_dssd_controller"
#define FLOPPY_FORMATS_END_NO_DEFAULTS ,\
NULL };
ti_fdc_device::ti_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: ti_expansion_card_device(mconfig, TI99_FDC, "TI-99 Standard DSSD Floppy Controller", tag, owner, clock, "ti99_fdc", __FILE__),
m_fd1771(*this, FDC_TAG) { }
/*
callback called at the end of DVENA pulse
*/
void ti_fdc_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
m_DVENA = CLEAR_LINE;
if (TRACE_MOTOR) logerror("tifdc: Motor off\n");
set_ready_line();
}
/*
Operate the wait state logic.
*/
void ti_fdc_device::set_ready_line()
void ti_fdc_device::operate_ready_line()
{
// This is the wait state logic
if (TRACE_SIGNALS) logerror("tifdc: address=%04x, DRQ=%d, INTRQ=%d, MOTOR=%d\n", m_address & 0xffff, m_DRQ, m_IRQ, m_DVENA);
@ -89,6 +72,29 @@ void ti_fdc_device::set_ready_line()
m_slot->set_ready((nready==CLEAR_LINE)? ASSERT_LINE : CLEAR_LINE);
}
/*
* Callbacks from the FD1771 chip
*/
void ti_fdc_device::irq_w(bool state)
{
m_IRQ = state? ASSERT_LINE : CLEAR_LINE;
if (TRACE_SIGNALS) logerror("tifdc: INTRQ callback = %d\n", m_IRQ);
operate_ready_line();
}
void ti_fdc_device::drq_w(bool state)
{
m_DRQ = state? ASSERT_LINE : CLEAR_LINE;
if (TRACE_SIGNALS) logerror("tifdc: DRQ callback = %d\n", m_DRQ);
operate_ready_line();
}
// bool ti_fdc_device::dvena_r()
// {
// if (TRACE_SIGNALS) logerror("tifdc: reading DVENA = %d\n", m_DVENA);
// return (m_DVENA==ASSERT_LINE);
// }
SETADDRESS_DBIN_MEMBER( ti_fdc_device::setaddress_dbin )
{
// Selection login in the PAL and some circuits on the board
@ -97,6 +103,378 @@ SETADDRESS_DBIN_MEMBER( ti_fdc_device::setaddress_dbin )
m_address = offset;
m_inDsrArea = ((m_address & m_select_mask)==m_select_value);
if (!m_inDsrArea || !m_selected) return;
if (TRACE_ADDRESS) logerror("tifdc: set address = %04x\n", offset & 0xffff);
// Is the WD chip on the card being selected?
m_WDsel = m_inDsrArea && ((m_address & 0x1ff1)==0x1ff0);
// Clear or assert the outgoing READY line
operate_ready_line();
}
READ8Z_MEMBER(ti_fdc_device::readz)
{
if (m_inDsrArea && m_selected)
{
// Read ports of 1771 are mapped to 5FF0,2,4,6: 0101 1111 1111 0xx0
// Note that incoming/outgoing data are inverted for FD1771
UINT8 reply = 0;
if (m_WDsel && ((m_address & 9)==0))
{
if (!space.debugger_access()) reply = m_fd1771->gen_r((offset >> 1)&0x03);
if (TRACE_DATA)
{
if ((m_address & 0xffff)==0x5ff6)
{
if (!m_debug_dataout) logerror("tifdc: Read data = ");
m_debug_dataout = true;
logerror("%02x ", ~reply & 0xff);
}
else
{
if (m_debug_dataout) logerror("\n");
m_debug_dataout = false;
}
}
}
else
{
reply = m_dsrrom[m_address & 0x1fff];
}
*value = reply;
if (TRACE_RW) logerror("tifdc: %04x -> %02x\n", offset & 0xffff, *value);
}
}
WRITE8_MEMBER(ti_fdc_device::write)
{
if (m_inDsrArea && m_selected)
{
// Write ports of 1771 are mapped to 5FF8,A,C,E: 0101 1111 1111 1xx0
// This is important for the TI console: The TMS9900 CPU always performs a
// read operation before the write operation, and if we did not use
// different read and write ports, it would attempt to read from the
// controller before passing a command or data
// to it. In the best case, nothing happens; in the worst case, status
// flags may be reset by the read operation.
// Note that incoming/outgoing data are inverted for FD1771
if (TRACE_RW) logerror("tifdc: %04x <- %02x\n", offset & 0xffff, ~data & 0xff);
if (m_WDsel && ((m_address & 9)==8))
{
// As this is a memory-mapped access we must prevent the debugger
// from messing with the operation
if (!space.debugger_access()) m_fd1771->gen_w((offset >> 1)&0x03, data);
}
}
}
/*
CRU read access
7 6 5 4 3 2 1 0
+-----+-----+-----+------+-----+-----+-----+-----+
| Side| 1 | 0 |DVENA*| DSK3| DSK2| DSK1| HLD |
+-----+-----+-----+------+-----+-----+-----+-----+
We have only 8 bits for query; within this implementation this means
we only use the base address (offset 0).
*/
READ8Z_MEMBER(ti_fdc_device::crureadz)
{
if ((offset & 0xff00)==m_cru_base)
{
UINT8 reply = 0;
if ((offset & 0x07) == 0)
{
// Selected drive
reply |= ((m_DSEL)<<1);
// The DVENA state is returned as inverted
if (m_DVENA==CLEAR_LINE) reply |= 0x10;
// Always 1
reply |= 0x40;
// Selected side
if (m_SIDSEL==ASSERT_LINE) reply |= 0x80;
}
*value = reply;
if (TRACE_CRU) logerror("tifdc: Read CRU = %02x\n", *value);
}
}
WRITE8_MEMBER(ti_fdc_device::cruwrite)
{
if ((offset & 0xff00)==m_cru_base)
{
int bit = (offset >> 1) & 0x07;
switch (bit)
{
case 0:
// (De)select the card. Indicated by a LED on the board.
m_selected = (data!=0);
if (TRACE_CRU) logerror("tifdc: Map DSR (bit 0) = %d\n", m_selected);
break;
case 1:
// Activate motor
if (data==1 && m_lastval==0)
{ // On rising edge, set motor_running for 4.23s
if (TRACE_CRU) logerror("tifdc: trigger motor (bit 1)\n");
set_floppy_motors_running(true);
m_motor_on_timer->adjust(attotime::from_msec(4230));
}
m_lastval = data;
break;
case 2:
// Set disk ready/hold (bit 2)
// 0: ignore IRQ and DRQ
// 1: TMS9900 is stopped until IRQ or DRQ are set
// OR the motor stops rotating - rotates for 4.23s after write
// to CRU bit 1
m_WAITena = (data != 0);
if (TRACE_CRU) logerror("tifdc: arm wait state logic (bit 2) = %d\n", data);
break;
case 3:
// Load disk heads (HLT pin) (bit 3). Not implemented.
if (TRACE_CRU) logerror("tifdc: set head load (bit 3) = %d\n", data);
break;
case 4:
m_DSEL = (data != 0)? (m_DSEL | 0x01) : (m_DSEL & 0xfe);
set_drive();
break;
case 5:
m_DSEL = (data != 0)? (m_DSEL | 0x02) : (m_DSEL & 0xfd);
set_drive();
break;
case 6:
m_DSEL = (data != 0)? (m_DSEL | 0x04) : (m_DSEL & 0xfb);
set_drive();
break;
case 7:
// Select side of disk (bit 7)
m_SIDSEL = (data==1)? ASSERT_LINE : CLEAR_LINE;
if (TRACE_CRU) logerror("tifdc: set side (bit 7) = %d\n", data);
if (m_current_floppy != NULL) m_current_floppy->ss_w(data);
break;
default:
break;
}
}
}
void ti_fdc_device::set_drive()
{
int i = -1;
switch (m_DSEL)
{
case 0:
m_current_floppy = NULL;
if (TRACE_CRU) logerror("tifdc: all drives deselected\n");
break;
case 1:
i = 0;
break;
case 2:
i = 1;
break;
case 3:
// The schematics do not reveal any countermeasures against multiple selection
// so we assume that the highest value wins.
i = 1;
logerror("tifdc: Warning - multiple drives selected\n");
break;
case 4:
i = 2;
break;
default:
i = 2;
logerror("tifdc: Warning - multiple drives selected\n");
break;
}
if (TRACE_CRU) logerror("tifdc: new DSEL = %d\n", m_DSEL);
if (i != -1) m_current_floppy = m_floppy[i];
m_fd1771->set_floppy(m_current_floppy);
}
/*
Monoflop has gone back to the OFF state.
*/
void ti_fdc_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
set_floppy_motors_running(false);
}
/*
All floppy motors are operated by the same line.
*/
void ti_fdc_device::set_floppy_motors_running(bool run)
{
if (TRACE_MOTOR)
{
if (m_DVENA==ASSERT_LINE && !run) logerror("tifdc: Motor STOP\n");
if (m_DVENA==CLEAR_LINE && run) logerror("tifdc: Motor START\n");
}
m_DVENA = (run)? ASSERT_LINE : CLEAR_LINE;
m_fd1771->set_force_ready(run);
for (int i=0; i < 3; i++)
if (m_floppy[i] != NULL) m_floppy[i]->mon_w((run)? 0 : 1);
operate_ready_line();
}
void ti_fdc_device::device_start()
{
logerror("tifdc: TI FDC start\n");
m_dsrrom = memregion(DSRROM)->base();
m_motor_on_timer = timer_alloc(MOTOR_TIMER);
m_cru_base = 0x1100;
m_fd1771->setup_intrq_cb(wd_fdc_t::line_cb(FUNC(ti_fdc_device::irq_w), this));
m_fd1771->setup_drq_cb(wd_fdc_t::line_cb(FUNC(ti_fdc_device::drq_w), this));
// In case we implement a callback after all:
// m_fd1771->setup_ready_cb(wd_fdc_t::rline_cb(FUNC(ti_fdc_device::dvena_r), this));
}
void ti_fdc_device::device_reset()
{
logerror("tifdc: TI FDC reset\n");
m_lastval = 0;
if (m_genmod)
{
m_select_mask = 0x1fe000;
m_select_value = 0x174000;
}
else
{
m_select_mask = 0x7e000;
m_select_value = 0x74000;
}
m_DRQ = CLEAR_LINE;
m_IRQ = CLEAR_LINE;
m_DVENA = CLEAR_LINE;
m_fd1771->set_force_ready(false);
m_DSEL = 0;
m_WAITena = false;
m_selected = false;
m_debug_dataout = false;
for (int i=0; i < 3; i++)
{
if (m_floppy[i] != NULL)
logerror("tifdc: Connector %d with %s\n", i, m_floppy[i]->name());
else
logerror("tifdc: No floppy attached to connector %d\n", i);
}
m_fd1771->set_floppy(m_current_floppy = m_floppy[0]);
}
void ti_fdc_device::device_config_complete()
{
// Seems to be null when doing a "-listslots"
if (subdevice("0")!=NULL) m_floppy[0] = static_cast<floppy_image_device*>(subdevice("0")->first_subdevice());
if (subdevice("1")!=NULL) m_floppy[1] = static_cast<floppy_image_device*>(subdevice("1")->first_subdevice());
if (subdevice("2")!=NULL) m_floppy[2] = static_cast<floppy_image_device*>(subdevice("2")->first_subdevice());
}
FLOPPY_FORMATS_MEMBER(ti_fdc_device::floppy_formats)
FLOPPY_TI99_SDF_FORMAT
FLOPPY_FORMATS_END_NO_DEFAULTS
static SLOT_INTERFACE_START( tifdc_floppies )
SLOT_INTERFACE( "525dd", FLOPPY_525_DD )
SLOT_INTERFACE_END
MACHINE_CONFIG_FRAGMENT( ti_fdc )
MCFG_FD1771x_ADD(FDC_TAG, XTAL_1MHz)
MCFG_FLOPPY_DRIVE_ADD("0", tifdc_floppies, "525dd", ti_fdc_device::floppy_formats)
MCFG_FLOPPY_DRIVE_ADD("1", tifdc_floppies, NULL, ti_fdc_device::floppy_formats)
MCFG_FLOPPY_DRIVE_ADD("2", tifdc_floppies, NULL, ti_fdc_device::floppy_formats)
MACHINE_CONFIG_END
ROM_START( ti_fdc )
ROM_REGION(0x2000, DSRROM, 0)
ROM_LOAD("disk.bin", 0x0000, 0x2000, CRC(8f7df93f) SHA1(ed91d48c1eaa8ca37d5055bcf67127ea51c4cad5)) /* TI disk DSR ROM */
ROM_END
machine_config_constructor ti_fdc_device::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME( ti_fdc );
}
const rom_entry *ti_fdc_device::device_rom_region() const
{
return ROM_NAME( ti_fdc );
}
const device_type TI99_FDC = &device_creator<ti_fdc_device>;
//===========================================================================
/***********************************************
Legacy implementation, to be removed
***********************************************/
#define TI_FDCLEG_TAG "ti_dssd_controller_legacy"
#define FDCLEG_TAG "wd1771"
const wd17xx_interface ti_wd17xx_interface =
{
DEVCB_NULL,
DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER, ti_fdc_legacy_device, intrq_w),
DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER, ti_fdc_legacy_device, drq_w),
{ PFLOPPY_0, PFLOPPY_1, PFLOPPY_2, NULL }
};
ti_fdc_legacy_device::ti_fdc_legacy_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: ti_expansion_card_device(mconfig, TI99_FDC_LEG, "TI-99 Standard DSSD Floppy Controller (legacy)", tag, owner, clock, "ti99_fdc", __FILE__),
m_fd1771(*this, FDCLEG_TAG) { }
/*
callback called at the end of DVENA pulse
*/
void ti_fdc_legacy_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
m_DVENA = CLEAR_LINE;
if (TRACE_MOTOR) logerror("tifdc: Motor off\n");
set_ready_line();
}
/*
Operate the wait state logic.
*/
void ti_fdc_legacy_device::set_ready_line()
{
// This is the wait state logic
if (TRACE_SIGNALS) logerror("tifdc: address=%04x, DRQ=%d, INTRQ=%d, MOTOR=%d\n", m_address & 0xffff, m_DRQ, m_IRQ, m_DVENA);
line_state nready = (m_WDsel && // Are we accessing 5ffx (even addr)?
m_WAITena && // and the wait state generation is active (SBO 2)
(m_DRQ==CLEAR_LINE) && // and we are waiting for a byte
(m_IRQ==CLEAR_LINE) && // and there is no interrupt yet
(m_DVENA==ASSERT_LINE) // and the motor is turning?
)? ASSERT_LINE : CLEAR_LINE; // In that case, clear READY and thus trigger wait states
if (TRACE_READY) logerror("tifdc: READY line = %d\n", (nready==CLEAR_LINE)? 1:0);
m_slot->set_ready((nready==CLEAR_LINE)? ASSERT_LINE : CLEAR_LINE);
}
SETADDRESS_DBIN_MEMBER( ti_fdc_legacy_device::setaddress_dbin )
{
// Selection login in the PAL and some circuits on the board
// Is the card being selected?
m_address = offset;
m_inDsrArea = ((m_address & m_select_mask)==m_select_value);
if (!m_inDsrArea) return;
if (TRACE_ADDRESS) logerror("tifdc: set address = %04x\n", offset & 0xffff);
@ -108,7 +486,7 @@ SETADDRESS_DBIN_MEMBER( ti_fdc_device::setaddress_dbin )
set_ready_line();
}
READ8Z_MEMBER(ti_fdc_device::readz)
READ8Z_MEMBER(ti_fdc_legacy_device::readz)
{
if (m_inDsrArea && m_selected)
{
@ -117,7 +495,7 @@ READ8Z_MEMBER(ti_fdc_device::readz)
// 0101 1111 1111 0xx0
UINT8 reply = 0;
if (m_WDsel && ((m_address & 1)==0))
if (m_WDsel && ((m_address & 9)==0))
{
if (!space.debugger_access()) reply = wd17xx_r(m_fd1771, space, (offset >> 1)&0x03);
if (TRACE_DATA)
@ -135,7 +513,7 @@ READ8Z_MEMBER(ti_fdc_device::readz)
}
}
WRITE8_MEMBER(ti_fdc_device::write)
WRITE8_MEMBER(ti_fdc_legacy_device::write)
{
if (m_inDsrArea && m_selected)
{
@ -159,7 +537,7 @@ WRITE8_MEMBER(ti_fdc_device::write)
bit 6: always 1
bit 7: selected side
*/
READ8Z_MEMBER(ti_fdc_device::crureadz)
READ8Z_MEMBER(ti_fdc_legacy_device::crureadz)
{
if ((offset & 0xff00)==m_cru_base)
{
@ -180,7 +558,7 @@ READ8Z_MEMBER(ti_fdc_device::crureadz)
}
}
WRITE8_MEMBER(ti_fdc_device::cruwrite)
WRITE8_MEMBER(ti_fdc_legacy_device::cruwrite)
{
int drive, drivebit;
@ -259,7 +637,7 @@ WRITE8_MEMBER(ti_fdc_device::cruwrite)
the default implementation sets the drive geometry to the geometry
of the medium.
*/
void ti_fdc_device::set_geometry(device_t *drive, floppy_type_t type)
void ti_fdc_legacy_device::set_geometry(device_t *drive, floppy_type_t type)
{
// This assertion may fail when the names of the floppy devices change.
// Unfortunately, the wd17xx device assumes the floppy drives at root
@ -268,7 +646,7 @@ void ti_fdc_device::set_geometry(device_t *drive, floppy_type_t type)
floppy_drive_set_geometry(drive, type);
}
void ti_fdc_device::set_all_geometries(floppy_type_t type)
void ti_fdc_legacy_device::set_all_geometries(floppy_type_t type)
{
set_geometry(machine().device(PFLOPPY_0), type);
set_geometry(machine().device(PFLOPPY_1), type);
@ -278,7 +656,7 @@ void ti_fdc_device::set_all_geometries(floppy_type_t type)
/*
Callback, called from the controller chip whenever DRQ/IRQ state change
*/
WRITE_LINE_MEMBER( ti_fdc_device::intrq_w )
WRITE_LINE_MEMBER( ti_fdc_legacy_device::intrq_w )
{
if (TRACE_SIGNALS) logerror("ti_fdc: set irq = %d\n", state);
m_IRQ = (line_state)state;
@ -289,24 +667,24 @@ WRITE_LINE_MEMBER( ti_fdc_device::intrq_w )
set_ready_line();
}
WRITE_LINE_MEMBER( ti_fdc_device::drq_w )
WRITE_LINE_MEMBER( ti_fdc_legacy_device::drq_w )
{
if (TRACE_SIGNALS) logerror("ti_fdc: set drq = %d\n", state);
m_DRQ = (line_state)state;
set_ready_line();
}
void ti_fdc_device::device_start(void)
void ti_fdc_legacy_device::device_start(void)
{
logerror("ti_fdc: TI FDC start\n");
logerror("ti_fdc: TI FDC (legacy) start\n");
m_dsrrom = memregion(DSRROM)->base();
m_motor_on_timer = timer_alloc(MOTOR_TIMER);
m_cru_base = 0x1100;
}
void ti_fdc_device::device_reset(void)
void ti_fdc_legacy_device::device_reset(void)
{
logerror("ti_fdc: TI FDC reset\n");
logerror("ti_fdc: TI FDC (legacy) reset\n");
m_DSEL = 0;
m_SIDSEL = 0;
m_DVENA = CLEAR_LINE;
@ -331,23 +709,23 @@ void ti_fdc_device::device_reset(void)
set_all_geometries(type);
}
MACHINE_CONFIG_FRAGMENT( ti_fdc )
MCFG_FD1771_ADD(FDC_TAG, ti_wd17xx_interface )
MACHINE_CONFIG_FRAGMENT( ti_fdc_legacy )
MCFG_FD1771_ADD(FDCLEG_TAG, ti_wd17xx_interface )
MACHINE_CONFIG_END
ROM_START( ti_fdc )
ROM_START( ti_fdc_legacy )
ROM_REGION(0x2000, DSRROM, 0)
ROM_LOAD("disk.bin", 0x0000, 0x2000, CRC(8f7df93f) SHA1(ed91d48c1eaa8ca37d5055bcf67127ea51c4cad5)) /* TI disk DSR ROM */
ROM_END
machine_config_constructor ti_fdc_device::device_mconfig_additions() const
machine_config_constructor ti_fdc_legacy_device::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME( ti_fdc );
return MACHINE_CONFIG_NAME( ti_fdc_legacy );
}
const rom_entry *ti_fdc_device::device_rom_region() const
const rom_entry *ti_fdc_legacy_device::device_rom_region() const
{
return ROM_NAME( ti_fdc );
return ROM_NAME( ti_fdc_legacy );
}
const device_type TI99_FDC = &device_creator<ti_fdc_device>;
const device_type TI99_FDC_LEG = &device_creator<ti_fdc_legacy_device>;

View File

@ -11,13 +11,12 @@
January 2012: rewritten as class (MZ)
****************************************************************************/
#ifndef __TIFDC__
#define __TIFDC__
#include "ti99defs.h"
#include "machine/wd17xx.h"
#include "imagedev/flopdrv.h"
#include "machine/wd_fdc.h"
#include "imagedev/floppy.h"
extern const device_type TI99_FDC;
@ -35,6 +34,109 @@ public:
DECLARE_READ8Z_MEMBER(crureadz);
DECLARE_WRITE8_MEMBER(cruwrite);
DECLARE_FLOPPY_FORMATS( floppy_formats );
void irq_w(bool state);
void drq_w(bool state);
// bool dvena_r();
protected:
void device_start();
void device_reset();
void device_config_complete();
const rom_entry *device_rom_region() const;
machine_config_constructor device_mconfig_additions() const;
void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
private:
// Wait state logic
void operate_ready_line();
// Set the current floppy
void set_drive();
// Operate the floppy motors
void set_floppy_motors_running(bool run);
// Recent address
int m_address;
// Holds the status of the DRQ and IRQ lines.
line_state m_DRQ, m_IRQ;
// Needed for triggering the motor monoflop
UINT8 m_lastval;
// Signal DVENA. When TRUE, makes some drive turning.
line_state m_DVENA;
// Set when address is in card area
bool m_inDsrArea;
// When TRUE the CPU is halted while DRQ/IRQ are true.
bool m_WAITena;
// WD chip selected
bool m_WDsel;
// Indicates which drive has been selected. Values are 0, 1, 2, and 4.
// 000 = no drive
// 001 = drive 1
// 010 = drive 2
// 100 = drive 3
int m_DSEL;
// Signal SIDSEL. 0 or 1, indicates the selected head.
line_state m_SIDSEL;
// count 4.23s from rising edge of motor_on
emu_timer* m_motor_on_timer;
// Link to the FDC1771 controller on the board.
required_device<fd1771_t> m_fd1771;
// DSR ROM
UINT8* m_dsrrom;
// Link to the attached floppy drives
floppy_image_device* m_floppy[3];
// Currently selected floppy drive
floppy_image_device* m_current_floppy;
// Debugging
bool m_debug_dataout;
};
//===========================================================================
/***********************************************
Legacy implementation
***********************************************/
#include "machine/wd17xx.h"
#include "imagedev/flopdrv.h"
extern const device_type TI99_FDC_LEG;
class ti_fdc_legacy_device : public ti_expansion_card_device
{
public:
ti_fdc_legacy_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
DECLARE_READ8Z_MEMBER(readz);
DECLARE_WRITE8_MEMBER(write);
DECLARE_SETADDRESS_DBIN_MEMBER(setaddress_dbin);
DECLARE_WRITE_LINE_MEMBER( intrq_w );
DECLARE_WRITE_LINE_MEMBER( drq_w );
DECLARE_READ8Z_MEMBER(crureadz);
DECLARE_WRITE8_MEMBER(cruwrite);
protected:
virtual void device_start(void);
virtual void device_reset(void);