(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. * always be done.
********************************************************************/ ********************************************************************/
#include "emu.h"
#include <string.h> #include <string.h>
#include <assert.h> #include <assert.h>
#include <time.h> #include <time.h>
@ -81,9 +82,231 @@
#include "imageutl.h" #include "imageutl.h"
#include "ti99_dsk.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 SECTOR_SIZE 256
#define TI99_IDAM_LENGTH 7 #define TI99_IDAM_LENGTH 7
/**************************************************************
Legacy implementation
**************************************************************/
/* /*
Determines whether we are using 80 track drives. This variable is Determines whether we are using 80 track drives. This variable is
necessary unless we get information about the dip necessary unless we get information about the dip

View File

@ -11,9 +11,42 @@
#define TI99_DSK_H #define TI99_DSK_H
#include "flopimg.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); LEGACY_FLOPPY_OPTIONS_EXTERN(ti99);
void ti99_set_80_track_drives(int use80); void ti99_set_80_track_drives(int use80);
extern const floppy_format_type FLOPPY_TI99_SDF_FORMAT;
#endif /* TI99_DSK_H */ #endif /* TI99_DSK_H */

View File

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

View File

@ -42,39 +42,22 @@
#define TRACE_MOTOR 0 #define TRACE_MOTOR 0
// ---------------------------------- // ----------------------------------
#define FDC_TAG "fd1771"
#define TI_FDC_TAG "ti_dssd_controller"
#define FDC_TAG "wd1771"
#define MOTOR_TIMER 1 #define MOTOR_TIMER 1
const wd17xx_interface ti_wd17xx_interface = #define TI_FDC_TAG "ti_dssd_controller"
{ #define FLOPPY_FORMATS_END_NO_DEFAULTS ,\
DEVCB_NULL, 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 }
};
ti_fdc_device::ti_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) 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__), : ti_expansion_card_device(mconfig, TI99_FDC, "TI-99 Standard DSSD Floppy Controller", tag, owner, clock, "ti99_fdc", __FILE__),
m_fd1771(*this, FDC_TAG) { } 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. 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 // 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); 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); 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 ) SETADDRESS_DBIN_MEMBER( ti_fdc_device::setaddress_dbin )
{ {
// Selection login in the PAL and some circuits on the board // 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_address = offset;
m_inDsrArea = ((m_address & m_select_mask)==m_select_value); 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 (!m_inDsrArea) return;
if (TRACE_ADDRESS) logerror("tifdc: set address = %04x\n", offset & 0xffff); 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(); set_ready_line();
} }
READ8Z_MEMBER(ti_fdc_device::readz) READ8Z_MEMBER(ti_fdc_legacy_device::readz)
{ {
if (m_inDsrArea && m_selected) if (m_inDsrArea && m_selected)
{ {
@ -117,7 +495,7 @@ READ8Z_MEMBER(ti_fdc_device::readz)
// 0101 1111 1111 0xx0 // 0101 1111 1111 0xx0
UINT8 reply = 0; 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 (!space.debugger_access()) reply = wd17xx_r(m_fd1771, space, (offset >> 1)&0x03);
if (TRACE_DATA) 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) if (m_inDsrArea && m_selected)
{ {
@ -159,7 +537,7 @@ WRITE8_MEMBER(ti_fdc_device::write)
bit 6: always 1 bit 6: always 1
bit 7: selected side bit 7: selected side
*/ */
READ8Z_MEMBER(ti_fdc_device::crureadz) READ8Z_MEMBER(ti_fdc_legacy_device::crureadz)
{ {
if ((offset & 0xff00)==m_cru_base) 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; int drive, drivebit;
@ -259,7 +637,7 @@ WRITE8_MEMBER(ti_fdc_device::cruwrite)
the default implementation sets the drive geometry to the geometry the default implementation sets the drive geometry to the geometry
of the medium. 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. // This assertion may fail when the names of the floppy devices change.
// Unfortunately, the wd17xx device assumes the floppy drives at root // 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); 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_0), type);
set_geometry(machine().device(PFLOPPY_1), 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 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); if (TRACE_SIGNALS) logerror("ti_fdc: set irq = %d\n", state);
m_IRQ = (line_state)state; m_IRQ = (line_state)state;
@ -289,24 +667,24 @@ WRITE_LINE_MEMBER( ti_fdc_device::intrq_w )
set_ready_line(); 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); if (TRACE_SIGNALS) logerror("ti_fdc: set drq = %d\n", state);
m_DRQ = (line_state)state; m_DRQ = (line_state)state;
set_ready_line(); 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_dsrrom = memregion(DSRROM)->base();
m_motor_on_timer = timer_alloc(MOTOR_TIMER); m_motor_on_timer = timer_alloc(MOTOR_TIMER);
m_cru_base = 0x1100; 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_DSEL = 0;
m_SIDSEL = 0; m_SIDSEL = 0;
m_DVENA = CLEAR_LINE; m_DVENA = CLEAR_LINE;
@ -331,23 +709,23 @@ void ti_fdc_device::device_reset(void)
set_all_geometries(type); set_all_geometries(type);
} }
MACHINE_CONFIG_FRAGMENT( ti_fdc ) MACHINE_CONFIG_FRAGMENT( ti_fdc_legacy )
MCFG_FD1771_ADD(FDC_TAG, ti_wd17xx_interface ) MCFG_FD1771_ADD(FDCLEG_TAG, ti_wd17xx_interface )
MACHINE_CONFIG_END MACHINE_CONFIG_END
ROM_START( ti_fdc ) ROM_START( ti_fdc_legacy )
ROM_REGION(0x2000, DSRROM, 0) ROM_REGION(0x2000, DSRROM, 0)
ROM_LOAD("disk.bin", 0x0000, 0x2000, CRC(8f7df93f) SHA1(ed91d48c1eaa8ca37d5055bcf67127ea51c4cad5)) /* TI disk DSR ROM */ ROM_LOAD("disk.bin", 0x0000, 0x2000, CRC(8f7df93f) SHA1(ed91d48c1eaa8ca37d5055bcf67127ea51c4cad5)) /* TI disk DSR ROM */
ROM_END 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) January 2012: rewritten as class (MZ)
****************************************************************************/ ****************************************************************************/
#ifndef __TIFDC__ #ifndef __TIFDC__
#define __TIFDC__ #define __TIFDC__
#include "ti99defs.h" #include "ti99defs.h"
#include "machine/wd17xx.h" #include "machine/wd_fdc.h"
#include "imagedev/flopdrv.h" #include "imagedev/floppy.h"
extern const device_type TI99_FDC; extern const device_type TI99_FDC;
@ -35,6 +34,109 @@ public:
DECLARE_READ8Z_MEMBER(crureadz); DECLARE_READ8Z_MEMBER(crureadz);
DECLARE_WRITE8_MEMBER(cruwrite); 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: protected:
virtual void device_start(void); virtual void device_start(void);
virtual void device_reset(void); virtual void device_reset(void);