(MESS) ti99: Removed legacy wd17xx controllers

This commit is contained in:
Michael Zapf 2015-06-03 21:59:26 +02:00
parent 381d3dd572
commit c01ee6740e
9 changed files with 443 additions and 1447 deletions

View File

@ -31,7 +31,7 @@
Known issues (Feb 2014): Known issues (Feb 2014):
1. The BwG controller cannot run with the Geneve or other non-9900 computers. - The BwG controller cannot run with the Geneve or other non-9900 computers.
The reason for that is the wait state logic. It assumes that when The reason for that is the wait state logic. It assumes that when
executing MOVB @>5FF6,*R2, first a value from 5FF7 is attempted to be read, executing MOVB @>5FF6,*R2, first a value from 5FF7 is attempted to be read,
just as the TI console does. In that case, wait states are inserted if just as the TI console does. In that case, wait states are inserted if
@ -39,12 +39,6 @@
only and therefore circumvent the wait state generation. This is in fact only and therefore circumvent the wait state generation. This is in fact
not an emulation glitch but the behavior of the real expansion card. not an emulation glitch but the behavior of the real expansion card.
Resolved issues (Feb 2014):
1. The BwG controller failed to read single-density disks. This only occurs
with the legacy implementation because the modern floppy implementation
reproduces the correct recording format on the medium, so the controller
actually detects FM or MFM.
*******************************************************************************/ *******************************************************************************/
@ -704,498 +698,3 @@ const rom_entry *snug_bwg_device::device_rom_region() const
} }
const device_type TI99_BWG = &device_creator<snug_bwg_device>; const device_type TI99_BWG = &device_creator<snug_bwg_device>;
// ==========================================================================
#define FDCLEG_TAG "wd1773"
/*
Legacy implementation
*/
snug_bwg_legacy_device::snug_bwg_legacy_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: ti_expansion_card_device(mconfig, TI99_BWG_LEG, "SNUG BwG Floppy Controller LEGACY", tag, owner, clock, "ti99_bwg_leg", __FILE__),
m_wd1773(*this, FDCLEG_TAG),
m_clock(*this, CLOCK_TAG) { }
/*
Callback called at the end of DVENA pulse
*/
void snug_bwg_legacy_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
m_DVENA = CLEAR_LINE;
set_ready_line();
}
/*
Operate the wait state logic.
*/
void snug_bwg_legacy_device::set_ready_line()
{
// This is the wait state logic
if (TRACE_SIGNALS) logerror("bwg: address=%04x, DRQ=%d, INTRQ=%d, MOTOR=%d\n", m_address & 0xffff, m_DRQ, m_IRQ, m_DVENA);
line_state nready = (m_dataregLB && // Are we accessing 5ff7
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) if (nready==ASSERT_LINE) logerror("bwg: READY line = %d\n", (nready==CLEAR_LINE)? 1:0);
m_slot->set_ready((nready==CLEAR_LINE)? ASSERT_LINE : CLEAR_LINE);
}
/*
Callback, called from the controller chip whenever DRQ/IRQ state change
*/
WRITE_LINE_MEMBER( snug_bwg_legacy_device::intrq_w )
{
if (TRACE_SIGNALS) logerror("bwg: set intrq = %d\n", state);
m_IRQ = (line_state)state;
// Note that INTB is actually not used in the TI-99 family. But the
// controller asserts the line nevertheless, probably intended for
// use in another planned TI system
m_slot->set_intb(state==ASSERT_LINE);
// We need to explicitly set the READY line to release the datamux
set_ready_line();
}
WRITE_LINE_MEMBER( snug_bwg_legacy_device::drq_w )
{
if (TRACE_SIGNALS) logerror("bwg: set drq = %d\n", state);
m_DRQ = (line_state)state;
// We need to explicitly set the READY line to release the datamux
set_ready_line();
}
SETADDRESS_DBIN_MEMBER( snug_bwg_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("bwg: set address = %04x\n", offset & 0xffff);
// Is the WD chip on the card being selected?
// We need the even and odd addresses for the wait state generation,
// but only the even addresses when we access it
m_WDsel0 = m_inDsrArea && !m_rtc_enabled
&& ((state==ASSERT_LINE && ((m_address & 0x1ff8)==0x1ff0)) // read
|| (state==CLEAR_LINE && ((m_address & 0x1ff8)==0x1ff8))); // write
m_WDsel = m_WDsel0 && ((m_address & 1)==0);
// Is the RTC selected on the card? (even addr)
m_RTCsel = m_inDsrArea && m_rtc_enabled && ((m_address & 0x1fe1)==0x1fe0);
// RTC disabled:
// 5c00 - 5fef: RAM
// 5ff0 - 5fff: Controller (f0 = status, f2 = track, f4 = sector, f6 = data)
// RTC enabled:
// 5c00 - 5fdf: RAM
// 5fe0 - 5fff: Clock (even addr)
// Is RAM selected? We just check for the last 1K and let the RTC or WD
// just take control before
m_lastK = m_inDsrArea && ((m_address & 0x1c00)==0x1c00);
// Is the data register port of the WD being selected?
// In fact, the address to read the data from is 5FF6, but the TI-99 datamux
// fetches both bytes from 5FF7 and 5FF6, the odd one first. The BwG uses
// the odd address to operate the READY line
m_dataregLB = m_WDsel0 && ((m_address & 0x07)==0x07);
// Clear or assert the outgoing READY line
set_ready_line();
}
/*
Read a byte from ROM, RAM, FDC, or RTC. See setaddress_dbin for selection
logic.
*/
READ8Z_MEMBER(snug_bwg_legacy_device::readz)
{
if (m_inDsrArea && m_selected)
{
// 010x xxxx xxxx xxxx
if (m_lastK)
{
// ...1 11xx xxxx xxxx
if (m_rtc_enabled)
{
if (m_RTCsel)
{
// .... ..11 111x xxx0
if (!space.debugger_access()) *value = m_clock->read(space, (m_address & 0x001e) >> 1);
if (TRACE_RW) logerror("bwg: read RTC: %04x -> %02x\n", m_address & 0xffff, *value);
}
else
{
*value = m_buffer_ram[(m_ram_page<<10) | (m_address & 0x03ff)];
if (TRACE_RW) logerror("bwg: read ram: %04x (page %d)-> %02x\n", m_address & 0xffff, m_ram_page, *value);
}
}
else
{
if (m_WDsel)
{
// .... ..11 1111 0xx0
// Note that the value is inverted again on the board,
// so we can drop the inversion
if (!space.debugger_access()) *value = m_wd1773->read(space, (m_address >> 1)&0x03);
if (TRACE_RW) logerror("bwg: read FDC: %04x -> %02x\n", m_address & 0xffff, *value);
if (TRACE_DATA)
{
if ((m_address & 0xffff)==0x5ff6) logerror("%02x ", *value);
else logerror("\n%04x: %02x", m_address&0xffff, *value);
}
}
else
{
*value = m_buffer_ram[(m_ram_page<<10) | (m_address & 0x03ff)];
if (TRACE_RW) logerror("bwg: read ram: %04x (page %d)-> %02x\n", m_address & 0xffff, m_ram_page, *value);
}
}
}
else
{
*value = m_dsrrom[(m_rom_page<<13) | (m_address & 0x1fff)];
if (TRACE_RW) logerror("bwg: read dsr: %04x (page %d)-> %02x\n", m_address & 0xffff, m_rom_page, *value);
}
}
}
/*
Resets the drive geometry. This is required because the heuristic of
the default implementation sets the drive geometry to the geometry
of the medium.
*/
void snug_bwg_legacy_device::set_geometry(legacy_floppy_image_device *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
// level, so we use an explicitly qualified tag. See peribox.h.
assert(drive != NULL);
drive->floppy_drive_set_geometry(type);
}
void snug_bwg_legacy_device::set_all_geometries(floppy_type_t type)
{
set_geometry(machine().device<legacy_floppy_image_device>(PFLOPPY_0), type);
set_geometry(machine().device<legacy_floppy_image_device>(PFLOPPY_1), type);
set_geometry(machine().device<legacy_floppy_image_device>(PFLOPPY_2), type);
}
/*
Write a byte
4000 - 5bff: ROM, ignore write (4 banks)
rtc disabled:
5c00 - 5fef: RAM
5ff0 - 5fff: Controller (f8 = command, fa = track, fc = sector, fe = data)
rtc enabled:
5c00 - 5fdf: RAM
5fe0 - 5fff: Clock (even addr)
*/
WRITE8_MEMBER(snug_bwg_legacy_device::write)
{
if (m_inDsrArea && m_selected)
{
if (m_lastK)
{
if (m_rtc_enabled)
{
if (m_RTCsel)
{
// .... ..11 111x xxx0
if (TRACE_RW) logerror("bwg: write RTC: %04x <- %02x\n", m_address & 0xffff, data);
if (!space.debugger_access()) m_clock->write(space, (m_address & 0x001e) >> 1, data);
}
else
{
if (TRACE_RW) logerror("bwg: write ram: %04x (page %d) <- %02x\n", m_address & 0xffff, m_ram_page, data);
m_buffer_ram[(m_ram_page<<10) | (m_address & 0x03ff)] = data;
}
}
else
{
if (m_WDsel)
{
// .... ..11 1111 1xx0
// Note that the value is inverted again on the board,
// so we can drop the inversion
if (TRACE_RW) logerror("bwg: write FDC: %04x <- %02x\n", m_address & 0xffff, data);
if (!space.debugger_access()) m_wd1773->write(space, (m_address >> 1)&0x03, data);
}
else
{
if (TRACE_RW) logerror("bwg: write ram: %04x (page %d) <- %02x\n", m_address & 0xffff, m_ram_page, data);
m_buffer_ram[(m_ram_page<<10) | (m_address & 0x03ff)] = data;
}
}
}
}
}
/*
CRU read handler. *=inverted.
bit 0: DSK4 connected*
bit 1: DSK1 connected*
bit 2: DSK2 connected*
bit 3: DSK3 connected*
bit 4: Dip 1
bit 5: Dip 2
bit 6: Dip 3
bit 7: Dip 4
*/
READ8Z_MEMBER(snug_bwg_legacy_device::crureadz)
{
UINT8 reply = 0;
if ((offset & 0xff00)==m_cru_base)
{
if ((offset & 0x00ff)==0)
{
// Assume that we have 4 drives connected
// If we want to do that properly, we need to check the actually
// available drives (not the images!). But why should we connect less?
reply = 0x00;
// DIP switches. Note that a closed switch means 0
// xx01 1111 11 = only dsk1; 10 = 1+2, 01=1/2/3, 00=1-4
if (m_dip1 != 0) reply |= 0x10;
if (m_dip2 != 0) reply |= 0x20;
reply |= (m_dip34 << 6);
*value = ~reply;
}
else
*value = 0;
if (TRACE_CRU) logerror("bwg: Read CRU = %02x\n", *value);
}
}
WRITE8_MEMBER(snug_bwg_legacy_device::cruwrite)
{
int drive, drivebit;
if ((offset & 0xff00)==m_cru_base)
{
int bit = (offset >> 1) & 0x0f;
switch (bit)
{
case 0:
/* (De)select the card. Indicated by a LED on the board. */
m_selected = (data != 0);
if (TRACE_CRU) logerror("bwg: Map DSR (bit 0) = %d\n", m_selected);
break;
case 1:
/* Activate motor */
if (data && !m_strobe_motor)
{ /* on rising edge, set motor_running for 4.23s */
if (TRACE_CRU) logerror("bwg: trigger motor (bit 1)\n");
m_DVENA = ASSERT_LINE;
m_motor_on_timer->adjust(attotime::from_msec(4230));
}
m_strobe_motor = (data != 0);
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
if (TRACE_CRU) logerror("bwg: arm wait state logic (bit 2) = %d\n", data);
m_WAITena = (data != 0);
break;
case 4:
case 5:
case 6:
case 8:
/* Select drive 0-2 (DSK1-DSK3) (bits 4-6) */
/* Select drive 3 (DSK4) (bit 8) */
drive = (bit == 8) ? 3 : (bit - 4); /* drive # (0-3) */
if (TRACE_CRU) logerror("bwg: set drive (bit %d) = %d\n", bit, data);
drivebit = 1<<drive;
if (data != 0)
{
if ((m_DSEL & drivebit) == 0) /* select drive */
{
if (m_DSEL != 0)
logerror("bwg: Multiple drives selected, %02x\n", m_DSEL);
m_DSEL |= drivebit;
m_wd1773->set_drive(drive);
}
}
else
m_DSEL &= ~drivebit;
break;
case 7:
/* Select side of disk (bit 7) */
m_SIDE = data;
if (TRACE_CRU) logerror("bwg: set side (bit 7) = %d\n", data);
m_wd1773->set_side(m_SIDE);
break;
case 10:
/* double density enable (active low) */
if (TRACE_CRU) logerror("bwg: set double density (bit 10) = %d\n", data);
m_wd1773->dden_w((data != 0) ? ASSERT_LINE : CLEAR_LINE);
break;
case 11:
/* EPROM A13 */
if (data != 0)
m_rom_page |= 1;
else
m_rom_page &= 0xfe; // 11111110
if (TRACE_CRU) logerror("bwg: set ROM page (bit 11) = %d, page = %d\n", bit, m_rom_page);
break;
case 13:
/* RAM A10 */
m_ram_page = data;
if (TRACE_CRU) logerror("bwg: set RAM page (bit 13) = %d, page = %d\n", bit, m_ram_page);
break;
case 14:
/* Override FDC with RTC (active high) */
if (TRACE_CRU) logerror("bwg: turn on RTC (bit 14) = %d\n", data);
m_rtc_enabled = (data != 0);
break;
case 15:
/* EPROM A14 */
if (data != 0)
m_rom_page |= 2;
else
m_rom_page &= 0xfd; // 11111101
if (TRACE_CRU) logerror("bwg: set ROM page (bit 15) = %d, page = %d\n", bit, m_rom_page);
break;
case 3:
if (TRACE_CRU) logerror("bwg: set head load (bit 3) = %d\n", data);
break;
case 9:
case 12:
/* Unused (bit 3, 9 & 12) */
if (TRACE_CRU) logerror("bwg: set unknown bit %d = %d\n", bit, data);
break;
}
}
}
void snug_bwg_legacy_device::device_start(void)
{
logerror("bwg: BWG start\n");
m_dsrrom = memregion(DSRROM)->base();
m_buffer_ram = memregion(BUFFER)->base();
m_motor_on_timer = timer_alloc(MOTOR_TIMER);
m_cru_base = 0x1100;
}
void snug_bwg_legacy_device::device_reset()
{
logerror("bwg: BWG reset\n");
if (m_genmod)
{
m_select_mask = 0x1fe000;
m_select_value = 0x174000;
}
else
{
m_select_mask = 0x7e000;
m_select_value = 0x74000;
}
m_strobe_motor = false;
m_DVENA = CLEAR_LINE;
m_DSEL = 0;
m_SIDE = 0;
ti99_set_80_track_drives(FALSE);
floppy_type_t type = FLOPPY_STANDARD_5_25_DSDD_40;
set_all_geometries(type);
m_DRQ = CLEAR_LINE;
m_IRQ = CLEAR_LINE;
m_WAITena = false;
m_rtc_enabled = false;
m_selected = false;
m_dataregLB = false;
m_inDsrArea = false;
m_dip1 = ioport("BWGDIP1")->read();
m_dip2 = ioport("BWGDIP2")->read();
m_dip34 = ioport("BWGDIP34")->read();
m_rom_page = 0;
m_ram_page = 0;
}
INPUT_PORTS_START( bwg_fdc_legacy )
PORT_START( "BWGDIP1" )
PORT_DIPNAME( 0x01, 0x00, "BwG step rate" )
PORT_DIPSETTING( 0x00, "6 ms")
PORT_DIPSETTING( 0x01, "20 ms")
PORT_START( "BWGDIP2" )
PORT_DIPNAME( 0x01, 0x00, "BwG date/time display" )
PORT_DIPSETTING( 0x00, "Hide")
PORT_DIPSETTING( 0x01, "Show")
PORT_START( "BWGDIP34" )
PORT_DIPNAME( 0x03, 0x03, "BwG drives" )
PORT_DIPSETTING( 0x00, "DSK1 only")
PORT_DIPSETTING( 0x01, "DSK1-DSK2")
PORT_DIPSETTING( 0x02, "DSK1-DSK3")
PORT_DIPSETTING( 0x03, "DSK1-DSK4")
INPUT_PORTS_END
MACHINE_CONFIG_FRAGMENT( bwg_fdc_legacy )
MCFG_DEVICE_ADD(FDCLEG_TAG, WD1773, 0)
MCFG_WD17XX_DEFAULT_DRIVE4_TAGS
MCFG_WD17XX_INTRQ_CALLBACK(WRITELINE(snug_bwg_legacy_device, intrq_w))
MCFG_WD17XX_DRQ_CALLBACK(WRITELINE(snug_bwg_legacy_device, drq_w))
MCFG_DEVICE_ADD(CLOCK_TAG, MM58274C, 0)
MCFG_MM58274C_MODE24(1) // 24 hour
MCFG_MM58274C_DAY1(0) // sunday
MACHINE_CONFIG_END
ROM_START( bwg_fdc_legacy )
ROM_REGION(0x8000, DSRROM, 0)
ROM_LOAD("bwg.bin", 0x0000, 0x8000, CRC(06f1ec89) SHA1(6ad77033ed268f986d9a5439e65f7d391c4b7651)) /* BwG disk DSR ROM */
ROM_REGION(0x0800, BUFFER, 0) /* BwG RAM buffer */
ROM_FILL(0x0000, 0x0400, 0x00)
ROM_END
machine_config_constructor snug_bwg_legacy_device::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME( bwg_fdc_legacy );
}
const rom_entry *snug_bwg_legacy_device::device_rom_region() const
{
return ROM_NAME( bwg_fdc_legacy );
}
ioport_constructor snug_bwg_legacy_device::device_input_ports() const
{
return INPUT_PORTS_NAME( bwg_fdc_legacy );
}
const device_type TI99_BWG_LEG = &device_creator<snug_bwg_legacy_device>;

View File

@ -20,9 +20,6 @@
extern const device_type TI99_BWG; extern const device_type TI99_BWG;
/*
Implementation for modern floppy system.
*/
class snug_bwg_device : public ti_expansion_card_device class snug_bwg_device : public ti_expansion_card_device
{ {
public: public:
@ -142,109 +139,4 @@ private:
// Debugging // Debugging
bool m_debug_dataout; bool m_debug_dataout;
}; };
// =========================================================================
/*
Legacy implementation.
*/
#include "machine/wd17xx.h"
extern const device_type TI99_BWG_LEG;
class snug_bwg_legacy_device : public ti_expansion_card_device
{
public:
snug_bwg_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);
virtual const rom_entry *device_rom_region() const;
virtual machine_config_constructor device_mconfig_additions() const;
virtual ioport_constructor device_input_ports() const;
private:
void set_ready_line();
void set_all_geometries(floppy_type_t type);
void set_geometry(legacy_floppy_image_device *drive, floppy_type_t type);
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
// Holds the status of the DRQ and IRQ lines.
line_state m_DRQ, m_IRQ;
// DIP switch state
int m_dip1, m_dip2, m_dip34;
// Page selection for ROM and RAM
int m_ram_page; // 0-1
int m_rom_page; // 0-3
// When true, the READY line will be cleared (create wait states) when
// waiting for data from the controller.
bool m_WAITena;
// Address in card area
bool m_inDsrArea;
// WD selected
bool m_WDsel, m_WDsel0;
// RTC selected
bool m_RTCsel;
// last 1K area selected
bool m_lastK;
// Data register +1 selected
bool m_dataregLB;
/* Indicates whether the clock is mapped into the address space. */
bool m_rtc_enabled;
/* When TRUE, keeps DVENA high. */
bool m_strobe_motor;
// Signal DVENA. When TRUE, makes some drive turning.
line_state m_DVENA;
// Recent address
int m_address;
/* 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. */
int m_SIDE;
// Link to the WD1773 controller on the board.
required_device<wd1773_device> m_wd1773;
// Link to the real-time clock on the board.
required_device<mm58274c_device> m_clock;
// count 4.23s from rising edge of motor_on
emu_timer* m_motor_on_timer;
// DSR ROM
UINT8* m_dsrrom;
// Buffer RAM
UINT8* m_buffer_ram;
};
#endif #endif

View File

@ -431,16 +431,13 @@ SLOT_INTERFACE_END
SLOT_INTERFACE_START( peribox_slot7 ) SLOT_INTERFACE_START( peribox_slot7 )
SLOT_INTERFACE("ide", TI99_IDE) SLOT_INTERFACE("ide", TI99_IDE)
SLOT_INTERFACE("usbsm", TI99_USBSM) SLOT_INTERFACE("usbsm", TI99_USBSM)
SLOT_INTERFACE("bwgleg", TI99_BWG_LEG)
SLOT_INTERFACE("bwg", TI99_BWG) SLOT_INTERFACE("bwg", TI99_BWG)
SLOT_INTERFACE("hfdc", TI99_HFDC_LEG) SLOT_INTERFACE("hfdc", TI99_HFDC_LEG)
SLOT_INTERFACE("hfdcnew", TI99_HFDC) SLOT_INTERFACE("hfdcnew", TI99_HFDC)
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("bwgleg", TI99_BWG_LEG)
SLOT_INTERFACE("bwg", TI99_BWG) SLOT_INTERFACE("bwg", TI99_BWG)
SLOT_INTERFACE("hfdc", TI99_HFDC_LEG) SLOT_INTERFACE("hfdc", TI99_HFDC_LEG)
SLOT_INTERFACE("hfdcnew", TI99_HFDC) SLOT_INTERFACE("hfdcnew", TI99_HFDC)
@ -497,7 +494,6 @@ 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_LEG) SLOT_INTERFACE("hfdc", TI99_HFDC_LEG)
SLOT_INTERFACE("hfdcnew", TI99_HFDC) SLOT_INTERFACE("hfdcnew", TI99_HFDC)

View File

@ -427,313 +427,3 @@ const rom_entry *ti_fdc_device::device_rom_region() const
} }
const device_type TI99_FDC = &device_creator<ti_fdc_device>; 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"
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_leg", __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);
// Is the WD chip on the card being selected?
m_WDsel = m_inDsrArea && ((m_address & 0x1ff1)==0x1ff0);
// Clear or assert the outgoing READY line
set_ready_line();
}
READ8Z_MEMBER(ti_fdc_legacy_device::readz)
{
if (m_inDsrArea && m_selected)
{
// only use the even addresses from 1ff0 to 1ff6.
// Note that data is inverted.
// 0101 1111 1111 0xx0
UINT8 reply = 0;
if (m_WDsel && ((m_address & 9)==0))
{
if (!space.debugger_access()) reply = m_fd1771->read(space, (offset >> 1)&0x03);
if (TRACE_DATA)
{
if ((m_address & 0xffff)==0x5ff6) logerror("%02x ", ~reply & 0xff);
else logerror("\n%04x: %02x", m_address&0xffff, ~reply & 0xff);
}
}
else
{
reply = m_dsrrom[m_address & 0x1fff];
}
*value = reply;
if (TRACE_RW) logerror("ti_fdc: %04x -> %02x\n", offset & 0xffff, *value);
}
}
WRITE8_MEMBER(ti_fdc_legacy_device::write)
{
if (m_inDsrArea && m_selected)
{
if (TRACE_RW) logerror("ti_fdc: %04x <- %02x\n", offset & 0xffff, ~data & 0xff);
// only use the even addresses from 1ff8 to 1ffe.
// Note that data is inverted.
// 0101 1111 1111 1xx0
if (m_WDsel && ((m_address & 9)==8))
{
if (!space.debugger_access()) m_fd1771->write(space, (offset >> 1)&0x03, data);
}
}
}
/*
The CRU read handler.
bit 0: HLD pin
bit 1-3: drive n active
bit 4: 0: motor strobe on
bit 5: always 0
bit 6: always 1
bit 7: selected side
*/
READ8Z_MEMBER(ti_fdc_legacy_device::crureadz)
{
if ((offset & 0xff00)==m_cru_base)
{
int addr = offset & 0x07;
UINT8 reply = 0;
if (addr == 0)
{
// deliver bits 0-7
// TODO: HLD pin
// The DVENA state is returned inverted
if (m_DVENA==ASSERT_LINE) reply |= ((m_DSEL)<<1);
else reply |= 0x10;
reply |= 0x40;
if (m_SIDSEL) reply |= 0x80;
}
*value = reply;
if (TRACE_CRU) logerror("tifdc: Read CRU = %02x\n", *value);
}
}
WRITE8_MEMBER(ti_fdc_legacy_device::cruwrite)
{
int drive, drivebit;
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");
m_DVENA = ASSERT_LINE;
if (TRACE_MOTOR) logerror("tifdc: motor on\n");
set_ready_line();
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:
case 5:
case 6:
/* Select drive X (bits 4-6) */
drive = bit-4; /* drive # (0-2) */
if (TRACE_CRU) logerror("tifdc: set drive (bit %d) = %d\n", bit, data);
drivebit = 1<<drive;
if (data != 0)
{
if ((m_DSEL & drivebit) == 0) /* select drive */
{
if (m_DSEL != 0)
logerror("tifdc: Multiple drives selected, %02x\n", m_DSEL);
m_DSEL |= drivebit;
m_fd1771->set_drive(drive);
}
}
else
m_DSEL &= ~drivebit;
break;
case 7:
/* Select side of disk (bit 7) */
m_SIDSEL = data;
if (TRACE_CRU) logerror("tifdc: set side (bit 7) = %d\n", data);
m_fd1771->set_side(data);
break;
}
}
}
/*
Resets the drive geometry. This is required because the heuristic of
the default implementation sets the drive geometry to the geometry
of the medium.
*/
void ti_fdc_legacy_device::set_geometry(legacy_floppy_image_device *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
// level, so we use an explicitly qualified tag. See peribox.h.
assert (drive!=NULL);
drive->floppy_drive_set_geometry(type);
}
void ti_fdc_legacy_device::set_all_geometries(floppy_type_t type)
{
set_geometry(machine().device<legacy_floppy_image_device>(PFLOPPY_0), type);
set_geometry(machine().device<legacy_floppy_image_device>(PFLOPPY_1), type);
set_geometry(machine().device<legacy_floppy_image_device>(PFLOPPY_2), type);
}
/*
Callback, called from the controller chip whenever DRQ/IRQ state change
*/
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;
// Note that INTB is actually not used in the TI-99 family. But the
// controller asserts the line nevertheless, probably intended for
// use in another planned TI system
m_slot->set_intb(state);
set_ready_line();
}
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_legacy_device::device_start(void)
{
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_legacy_device::device_reset(void)
{
logerror("ti_fdc: TI FDC (legacy) reset\n");
m_DSEL = 0;
m_SIDSEL = 0;
m_DVENA = CLEAR_LINE;
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_WAITena = false;
m_selected = false;
m_inDsrArea = false;
m_WDsel = false;
ti99_set_80_track_drives(FALSE);
floppy_type_t type = FLOPPY_STANDARD_5_25_DSDD_40;
set_all_geometries(type);
}
MACHINE_CONFIG_FRAGMENT( ti_fdc_legacy )
MCFG_DEVICE_ADD(FDCLEG_TAG, FD1771, 0)
MCFG_WD17XX_DRIVE_TAGS(PFLOPPY_0, PFLOPPY_1, PFLOPPY_2, NULL)
MCFG_WD17XX_INTRQ_CALLBACK(WRITELINE(ti_fdc_legacy_device, intrq_w))
MCFG_WD17XX_DRQ_CALLBACK(WRITELINE(ti_fdc_legacy_device, drq_w))
MACHINE_CONFIG_END
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_legacy_device::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME( ti_fdc_legacy );
}
const rom_entry *ti_fdc_legacy_device::device_rom_region() const
{
return ROM_NAME( ti_fdc_legacy );
}
const device_type TI99_FDC_LEG = &device_creator<ti_fdc_legacy_device>;

View File

@ -108,85 +108,4 @@ private:
// Debugging // Debugging
bool m_debug_dataout; 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);
virtual const rom_entry *device_rom_region() const;
virtual machine_config_constructor device_mconfig_additions() const;
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
private:
void set_ready_line();
void set_all_geometries(floppy_type_t type);
void set_geometry(legacy_floppy_image_device *drive, floppy_type_t type);
// 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;
// When TRUE the CPU is halted while DRQ/IRQ are true.
bool m_WAITena;
// WD chip selected
bool m_WDsel;
// Set when address is in card area
bool m_inDsrArea;
// 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.
int 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_device> m_fd1771;
// DSR ROM
UINT8* m_dsrrom;
};
#endif #endif

View File

@ -24,37 +24,37 @@
#include "hdc9234.h" #include "hdc9234.h"
// Per-command debugging // Per-command debugging
#define TRACE_SELECT 1 #define TRACE_SELECT 0
#define TRACE_STEP 1 #define TRACE_STEP 0
#define TRACE_RESTORE 1 #define TRACE_RESTORE 0
#define TRACE_SUBSTATES 1 #define TRACE_SUBSTATES 0
#define TRACE_READ 1 #define TRACE_READ 0
#define TRACE_WRITE 1 #define TRACE_WRITE 0
#define TRACE_READREG 1 #define TRACE_READREG 0
#define TRACE_SETREG 1 #define TRACE_SETREG 0
#define TRACE_SETPTR 1 #define TRACE_SETPTR 0
#define TRACE_FORMAT 1 #define TRACE_FORMAT 0
#define TRACE_READTRACK 1 #define TRACE_READTRACK 0
// Common states // Common states
#define TRACE_READID 1 #define TRACE_READID 0
#define TRACE_VERIFY 1 #define TRACE_VERIFY 0
#define TRACE_TRANSFER 1 #define TRACE_TRANSFER 0
// Live states debugging // Live states debugging
#define TRACE_LIVE 1 #define TRACE_LIVE 0
#define TRACE_SHIFT 1 #define TRACE_SHIFT 0
#define TRACE_SYNC 1 #define TRACE_SYNC 0
// Misc debugging // Misc debugging
#define TRACE_DELAY 0 #define TRACE_DELAY 0
#define TRACE_INT 1 #define TRACE_INT 0
#define TRACE_LINES 1 #define TRACE_LINES 0
#define TRACE_INDEX 1 #define TRACE_INDEX 0
#define TRACE_DMA 1 #define TRACE_DMA 0
#define TRACE_DONE 1 #define TRACE_DONE 0
#define TRACE_FAIL 1 #define TRACE_FAIL 0
#define TRACE_AUXBUS 1 #define TRACE_AUXBUS 0
#define TRACE_DETAIL 0 #define TRACE_DETAIL 0

View File

@ -44,7 +44,6 @@ TODO:
#include "sound/beep.h" #include "sound/beep.h"
#include "video/733_asr.h" #include "video/733_asr.h"
#include "imagedev/flopdrv.h"
#include "machine/ti99/990_dk.h" #include "machine/ti99/990_dk.h"
@ -262,12 +261,12 @@ static ADDRESS_MAP_START(cru_map_v, AS_IO, 8, ti990_4_state )
ADDRESS_MAP_END ADDRESS_MAP_END
static const floppy_interface ti990_4_floppy_interface = /* static const floppy_interface ti990_4_floppy_interface =
{ {
FLOPPY_STANDARD_8_DSSD, FLOPPY_STANDARD_8_DSSD,
LEGACY_FLOPPY_OPTIONS_NAME(fd800), LEGACY_FLOPPY_OPTIONS_NAME(fd800),
NULL NULL
}; }; */
MACHINE_RESET_MEMBER(ti990_4_state,ti990_4) MACHINE_RESET_MEMBER(ti990_4_state,ti990_4)
{ {
@ -300,7 +299,7 @@ static MACHINE_CONFIG_START( ti990_4, ti990_4_state )
MCFG_DEVICE_ADD("fd800", FD800, 0) MCFG_DEVICE_ADD("fd800", FD800, 0)
MCFG_FD800_INT_HANDLER(WRITELINE(ti990_4_state, fd_interrupt)) MCFG_FD800_INT_HANDLER(WRITELINE(ti990_4_state, fd_interrupt))
MCFG_LEGACY_FLOPPY_4_DRIVES_ADD(ti990_4_floppy_interface) // MCFG_LEGACY_FLOPPY_4_DRIVES_ADD(ti990_4_floppy_interface)
MACHINE_CONFIG_END MACHINE_CONFIG_END
static MACHINE_CONFIG_START( ti990_4v, ti990_4_state ) static MACHINE_CONFIG_START( ti990_4v, ti990_4_state )
@ -320,7 +319,7 @@ static MACHINE_CONFIG_START( ti990_4v, ti990_4_state )
MCFG_DEVICE_ADD("fd800", FD800, 0) MCFG_DEVICE_ADD("fd800", FD800, 0)
MCFG_FD800_INT_HANDLER(WRITELINE(ti990_4_state, fd_interrupt)) MCFG_FD800_INT_HANDLER(WRITELINE(ti990_4_state, fd_interrupt))
MCFG_LEGACY_FLOPPY_4_DRIVES_ADD(ti990_4_floppy_interface) // MCFG_LEGACY_FLOPPY_4_DRIVES_ADD(ti990_4_floppy_interface)
MACHINE_CONFIG_END MACHINE_CONFIG_END
/* /*

View File

@ -17,7 +17,6 @@
#include "emu.h" #include "emu.h"
#include "formats/basicdsk.h"
#include "990_dk.h" #include "990_dk.h"
/* status bits */ /* status bits */
@ -104,14 +103,14 @@ void fd800_machine_init(void (*interrupt_callback)(running_machine &machine, int
*/ */
int fd800_legacy_device::read_id(int unit, int head, int *cylinder_id, int *sector_id) int fd800_legacy_device::read_id(int unit, int head, int *cylinder_id, int *sector_id)
{ {
/*UINT8 revolution_count;*/ //UINT8 revolution_count;*/
chrn_id id; // chrn_id id;
/*revolution_count = 0;*/ //revolution_count = 0;*/
/*while (revolution_count < 2)*/ /*while (revolution_count < 2)*/
/*{*/ /*{*/
if (m_drv[unit].img->floppy_drive_get_next_id(head, &id)) /* if (m_drv[unit].img->floppy_drive_get_next_id(head, &id))
{ {
if (cylinder_id) if (cylinder_id)
*cylinder_id = id.C; *cylinder_id = id.C;
@ -119,7 +118,7 @@ int fd800_legacy_device::read_id(int unit, int head, int *cylinder_id, int *sect
*sector_id = id.R; *sector_id = id.R;
return TRUE; return TRUE;
} }
/*}*/ }*/
return FALSE; return FALSE;
} }
@ -136,7 +135,7 @@ int fd800_legacy_device::read_id(int unit, int head, int *cylinder_id, int *sect
*/ */
int fd800_legacy_device::find_sector(int unit, int head, int sector, int *data_id) int fd800_legacy_device::find_sector(int unit, int head, int sector, int *data_id)
{ {
UINT8 revolution_count; /* UINT8 revolution_count;
chrn_id id; chrn_id id;
revolution_count = 0; revolution_count = 0;
@ -145,17 +144,17 @@ int fd800_legacy_device::find_sector(int unit, int head, int sector, int *data_i
{ {
if (m_drv[unit].img->floppy_drive_get_next_id(head, &id)) if (m_drv[unit].img->floppy_drive_get_next_id(head, &id))
{ {
/* compare id */ // compare id
if ((id.R == sector) && (id.N == 0)) if ((id.R == sector) && (id.N == 0))
{ {
*data_id = id.data_id; *data_id = id.data_id;
/* get ddam status */ // get ddam status
/*w->ddam = id.flags & ID_FLAG_DELETED_DATA;*/ // w->ddam = id.flags & ID_FLAG_DELETED_DATA;
return TRUE; return TRUE;
} }
} }
} }
*/
return FALSE; return FALSE;
} }
@ -170,7 +169,7 @@ int fd800_legacy_device::find_sector(int unit, int head, int sector, int *data_i
*/ */
int fd800_legacy_device::do_seek(int unit, int cylinder, int head) int fd800_legacy_device::do_seek(int unit, int cylinder, int head)
{ {
int retries; /* int retries;
if (cylinder > 76) if (cylinder > 76)
{ {
@ -180,46 +179,47 @@ int fd800_legacy_device::do_seek(int unit, int cylinder, int head)
if (m_drv[unit].img == NULL || !m_drv[unit].img->exists()) if (m_drv[unit].img == NULL || !m_drv[unit].img->exists())
{ {
m_stat_reg |= status_drv_not_ready; /* right??? */ m_stat_reg |= status_drv_not_ready;
return TRUE; return TRUE;
} }
if (m_drv[unit].log_cylinder[head] == -1) if (m_drv[unit].log_cylinder[head] == -1)
{ /* current track ID is unknown: read it */ {
if (!read_id(unit, head, &m_drv[unit].log_cylinder[head], NULL)) if (!read_id(unit, head, &m_drv[unit].log_cylinder[head], NULL))
{ {
m_stat_reg |= status_ID_not_found; m_stat_reg |= status_ID_not_found;
return TRUE; return TRUE;
} }
} }
/* exit if we are already at the requested track */
if (m_drv[unit].log_cylinder[head] == cylinder) if (m_drv[unit].log_cylinder[head] == cylinder)
{ {
/*m_stat_reg |= status_OP_complete;*/
return FALSE; return FALSE;
} }
for (retries=0; retries<10; retries++) for (retries=0; retries<10; retries++)
{ /* seek to requested track */ {
m_drv[unit].img->floppy_drive_seek(cylinder-m_drv[unit].log_cylinder[head]); m_drv[unit].img->floppy_drive_seek(cylinder-m_drv[unit].log_cylinder[head]);
/* update physical track position */
if (m_drv[unit].phys_cylinder != -1) if (m_drv[unit].phys_cylinder != -1)
m_drv[unit].phys_cylinder += cylinder-m_drv[unit].log_cylinder[head]; m_drv[unit].phys_cylinder += cylinder-m_drv[unit].log_cylinder[head];
/* read new track ID */
if (!read_id(unit, head, &m_drv[unit].log_cylinder[head], NULL)) if (!read_id(unit, head, &m_drv[unit].log_cylinder[head], NULL))
{ {
m_drv[unit].log_cylinder[head] = -1; m_drv[unit].log_cylinder[head] = -1;
m_stat_reg |= status_ID_not_found; m_stat_reg |= status_ID_not_found;
return TRUE; return TRUE;
} }
/* exit if we have reached the requested track */
if (m_drv[unit].log_cylinder[head] == cylinder) if (m_drv[unit].log_cylinder[head] == cylinder)
{ {
/*m_stat_reg |= status_OP_complete;*/
return FALSE; return FALSE;
} }
} }
/* track not found */
m_stat_reg |= status_seek_err; m_stat_reg |= status_seek_err;
*/
return TRUE; return TRUE;
} }
@ -232,16 +232,16 @@ int fd800_legacy_device::do_seek(int unit, int cylinder, int head)
*/ */
int fd800_legacy_device::do_restore(int unit) int fd800_legacy_device::do_restore(int unit)
{ {
int seek_count = 0; int seek_complete = 0;
int seek_complete; /* int seek_count = 0;
if (!m_drv[unit].img->exists()) if (!m_drv[unit].img->exists())
{ {
m_stat_reg |= status_drv_not_ready; /* right??? */ m_stat_reg |= status_drv_not_ready;
return TRUE; return TRUE;
} }
/* limit iterations to 76 to prevent an endless loop if the disc is locked */
while (!(seek_complete = !m_drv[unit].img->floppy_tk00_r()) && (seek_count < 76)) while (!(seek_complete = !m_drv[unit].img->floppy_tk00_r()) && (seek_count < 76))
{ {
m_drv[unit].img->floppy_drive_seek(-1); m_drv[unit].img->floppy_drive_seek(-1);
@ -255,9 +255,9 @@ int fd800_legacy_device::do_restore(int unit)
else else
{ {
m_drv[unit].phys_cylinder = 0; m_drv[unit].phys_cylinder = 0;
/*m_stat_reg |= status_OP_complete;*/
}
}
*/
return ! seek_complete; return ! seek_complete;
} }
@ -266,7 +266,7 @@ int fd800_legacy_device::do_restore(int unit)
*/ */
void fd800_legacy_device::do_read(void) void fd800_legacy_device::do_read(void)
{ {
int data_id; /* int data_id;
if ((m_sector == 0) || (m_sector > 26)) if ((m_sector == 0) || (m_sector > 26))
{ {
@ -286,7 +286,8 @@ void fd800_legacy_device::do_read(void)
m_recv_buf = (m_buf[m_buf_pos<<1] << 8) | m_buf[(m_buf_pos<<1)+1]; m_recv_buf = (m_buf[m_buf_pos<<1] << 8) | m_buf[(m_buf_pos<<1)+1];
m_stat_reg |= status_XFER_ready; m_stat_reg |= status_XFER_ready;
m_stat_reg |= status_OP_complete; /* right??? */ m_stat_reg |= status_OP_complete;
*/
} }
/* /*
@ -294,10 +295,9 @@ void fd800_legacy_device::do_read(void)
*/ */
void fd800_legacy_device::do_write(void) void fd800_legacy_device::do_write(void)
{ {
int data_id; /* int data_id;
if (m_drv[m_unit].seclen < 64) if (m_drv[m_unit].seclen < 64)
/* fill with 0s */
memset(m_buf+(m_drv[m_unit].seclen<<1), 0, (64-m_drv[m_unit].seclen)<<1); memset(m_buf+(m_drv[m_unit].seclen<<1), 0, (64-m_drv[m_unit].seclen)<<1);
if (!find_sector(m_unit, m_head, m_sector, &data_id)) if (!find_sector(m_unit, m_head, m_sector, &data_id))
@ -311,7 +311,8 @@ void fd800_legacy_device::do_write(void)
m_buf_mode = bm_write; m_buf_mode = bm_write;
m_stat_reg |= status_XFER_ready; m_stat_reg |= status_XFER_ready;
m_stat_reg |= status_OP_complete; /* right??? */ m_stat_reg |= status_OP_complete;
*/
} }
/* /*
@ -319,6 +320,7 @@ void fd800_legacy_device::do_write(void)
*/ */
void fd800_legacy_device::do_cmd(void) void fd800_legacy_device::do_cmd(void)
{ {
/*
int unit; int unit;
int cylinder; int cylinder;
int head; int head;
@ -327,10 +329,10 @@ void fd800_legacy_device::do_cmd(void)
if (m_buf_mode != bm_off) if (m_buf_mode != bm_off)
{ /* All commands in the midst of read or write are interpreted as Stop */ { // All commands in the midst of read or write are interpreted as Stop
unit = (m_cmd_reg >> 10) & 3; unit = (m_cmd_reg >> 10) & 3;
/* reset status */ // reset status
m_stat_reg = unit << status_unit_shift; m_stat_reg = unit << status_unit_shift;
m_buf_pos = 0; m_buf_pos = 0;
@ -346,16 +348,16 @@ void fd800_legacy_device::do_cmd(void)
switch (m_cmd_reg >> 12) switch (m_cmd_reg >> 12)
{ {
case 0: /* select case 0: // select
bits 16-25: 0s // bits 16-25: 0s
bits 26-27: unit number (0-3) */ // bits 26-27: unit number (0-3)
unit = (m_cmd_reg >> 10) & 3; unit = (m_cmd_reg >> 10) & 3;
/* reset status */ // reset status
m_stat_reg = unit << status_unit_shift; m_stat_reg = unit << status_unit_shift;
if (!m_drv[unit].img->exists()) if (!m_drv[unit].img->exists())
m_stat_reg |= status_drv_not_ready; /* right??? */ m_stat_reg |= status_drv_not_ready; // right???
else if (m_drv[unit].img->is_readonly()) else if (m_drv[unit].img->is_readonly())
m_stat_reg |= status_write_prot; m_stat_reg |= status_write_prot;
else else
@ -365,16 +367,16 @@ void fd800_legacy_device::do_cmd(void)
set_interrupt_line(); set_interrupt_line();
break; break;
case 1: /* seek case 1: // seek
bits 16-22: cylinder number (0-76) bits 16-22: cylinder number (0-76)
bits 23-24: 0s bits 23-24: 0s
bits 25: head number (1=upper) bits 25: head number (1=upper)
bits 26-27: unit number (0-3) */ bits 26-27: unit number (0-3)
unit = (m_cmd_reg >> 10) & 3; unit = (m_cmd_reg >> 10) & 3;
head = (m_cmd_reg >> 9) & 1; head = (m_cmd_reg >> 9) & 1;
cylinder = m_cmd_reg & 0x7f; cylinder = m_cmd_reg & 0x7f;
/* reset status */ // reset status
m_stat_reg = unit << status_unit_shift; m_stat_reg = unit << status_unit_shift;
if (!do_seek(unit, cylinder, head)) if (!do_seek(unit, cylinder, head))
@ -384,12 +386,12 @@ void fd800_legacy_device::do_cmd(void)
set_interrupt_line(); set_interrupt_line();
break; break;
case 2: /* restore case 2: // restore
bits 16-25: 0s bits 16-25: 0s
bits 26-27: unit number (0-3) */ bits 26-27: unit number (0-3)
unit = (m_cmd_reg >> 10) & 3; unit = (m_cmd_reg >> 10) & 3;
/* reset status */ // reset status
m_stat_reg = unit << status_unit_shift; m_stat_reg = unit << status_unit_shift;
if (!do_restore(unit)) if (!do_restore(unit))
@ -399,14 +401,14 @@ void fd800_legacy_device::do_cmd(void)
set_interrupt_line(); set_interrupt_line();
break; break;
case 3: /* sector length case 3: // sector length
bits 16-22: sector word count (0-64) bits 16-22: sector word count (0-64)
bits 23-25: 0s bits 23-25: 0s
bits 26-27: unit number (0-3) */ bits 26-27: unit number (0-3)
unit = (m_cmd_reg >> 10) & 3; unit = (m_cmd_reg >> 10) & 3;
seclen = m_cmd_reg & 0x7f; seclen = m_cmd_reg & 0x7f;
/* reset status */ // reset status
m_stat_reg = unit << status_unit_shift; m_stat_reg = unit << status_unit_shift;
if ((seclen > 64) || (seclen == 0)) if ((seclen > 64) || (seclen == 0))
@ -423,23 +425,23 @@ void fd800_legacy_device::do_cmd(void)
set_interrupt_line(); set_interrupt_line();
break; break;
case 4: /* read case 4: // read
bits 16-20: sector number (1-26) bits 16-20: sector number (1-26)
bits 21-23: 0s bits 21-23: 0s
bit 24: no sequential sectoring (1=active) bit 24: no sequential sectoring (1=active)
bit 25: head number (1=upper) bit 25: head number (1=upper)
bits 26-27: unit number (0-3) */ bits 26-27: unit number (0-3)
unit = (m_cmd_reg >> 10) & 3; unit = (m_cmd_reg >> 10) & 3;
head = (m_cmd_reg >> 9) & 1; head = (m_cmd_reg >> 9) & 1;
/*non_seq_mode = (m_cmd_reg >> 8) & 1;*/ //non_seq_mode = (m_cmd_reg >> 8) & 1;
sector = m_cmd_reg & 0x1f; sector = m_cmd_reg & 0x1f;
m_unit = unit; m_unit = unit;
m_head = head; m_head = head;
m_sector = sector; m_sector = sector;
/*m_non_seq_mode = non_seq_mode;*/ //m_non_seq_mode = non_seq_mode;
/* reset status */ // reset status
m_stat_reg = unit << status_unit_shift; m_stat_reg = unit << status_unit_shift;
do_read(); do_read();
@ -448,14 +450,14 @@ void fd800_legacy_device::do_cmd(void)
set_interrupt_line(); set_interrupt_line();
break; break;
case 5: /* read ID case 5: // read ID
bits 16-24: 0s bits 16-24: 0s
bit 25: head number (1=upper) bit 25: head number (1=upper)
bits 26-27: unit number (0-3) */ bits 26-27: unit number (0-3)
unit = (m_cmd_reg >> 10) & 3; unit = (m_cmd_reg >> 10) & 3;
head = (m_cmd_reg >> 9) & 1; head = (m_cmd_reg >> 9) & 1;
/* reset status */ // reset status
m_stat_reg = unit << status_unit_shift; m_stat_reg = unit << status_unit_shift;
if (!read_id(unit, head, &cylinder, &sector)) if (!read_id(unit, head, &cylinder, &sector))
@ -472,24 +474,24 @@ void fd800_legacy_device::do_cmd(void)
set_interrupt_line(); set_interrupt_line();
break; break;
case 6: /* read unformatted case 6: // read unformatted
bits 16-20: sector number (1-26) bits 16-20: sector number (1-26)
bits 21-24: 0s bits 21-24: 0s
bit 25: head number (1=upper) bit 25: head number (1=upper)
bits 26-27: unit number (0-3) */ bits 26-27: unit number (0-3)
/* ... */ // ...
break; break;
case 7: /* write case 7: // write
bits 16-20: sector number (1-26) bits 16-20: sector number (1-26)
bits 21-24: 0s bits 21-24: 0s
bit 25: head number (1=upper) bit 25: head number (1=upper)
bits 26-27: unit number (0-3) */ bits 26-27: unit number (0-3)
unit = (m_cmd_reg >> 10) & 3; unit = (m_cmd_reg >> 10) & 3;
head = (m_cmd_reg >> 9) & 1; head = (m_cmd_reg >> 9) & 1;
sector = m_cmd_reg & 0x1f; sector = m_cmd_reg & 0x1f;
/* reset status */ // reset status
m_stat_reg = unit << status_unit_shift; m_stat_reg = unit << status_unit_shift;
if ((m_sector == 0) || (m_sector > 26)) if ((m_sector == 0) || (m_sector > 26))
@ -506,23 +508,23 @@ void fd800_legacy_device::do_cmd(void)
m_buf_pos = 0; m_buf_pos = 0;
m_buf_mode = bm_write; m_buf_mode = bm_write;
m_stat_reg |= status_XFER_ready; m_stat_reg |= status_XFER_ready;
m_stat_reg |= status_OP_complete; /* right??? */ m_stat_reg |= status_OP_complete; // right???
} }
m_stat_reg |= status_interrupt; m_stat_reg |= status_interrupt;
set_interrupt_line(); set_interrupt_line();
break; break;
case 8: /* write delete case 8: // write delete
bits 16-20: sector number (1-26) bits 16-20: sector number (1-26)
bits 21-24: 0s bits 21-24: 0s
bit 25: head number (1=upper) bit 25: head number (1=upper)
bits 26-27: unit number (0-3) */ bits 26-27: unit number (0-3)
unit = (m_cmd_reg >> 10) & 3; unit = (m_cmd_reg >> 10) & 3;
head = (m_cmd_reg >> 9) & 1; head = (m_cmd_reg >> 9) & 1;
sector = m_cmd_reg & 0x1f; sector = m_cmd_reg & 0x1f;
/* reset status */ // reset status
m_stat_reg = unit << status_unit_shift; m_stat_reg = unit << status_unit_shift;
if ((m_sector == 0) || (m_sector > 26)) if ((m_sector == 0) || (m_sector > 26))
@ -539,34 +541,34 @@ void fd800_legacy_device::do_cmd(void)
m_buf_pos = 0; m_buf_pos = 0;
m_buf_mode = bm_write; m_buf_mode = bm_write;
m_stat_reg |= status_XFER_ready; m_stat_reg |= status_XFER_ready;
m_stat_reg |= status_OP_complete; /* right??? */ m_stat_reg |= status_OP_complete; // right???
} }
m_stat_reg |= status_interrupt; m_stat_reg |= status_interrupt;
set_interrupt_line(); set_interrupt_line();
break; break;
case 9: /* format track case 9: // format track
bits 16-23: track ID (0-255, normally current cylinder index, or 255 for bad track) bits 16-23: track ID (0-255, normally current cylinder index, or 255 for bad track)
bit 24: verify only (1 - verify, 0 - format & verify) bit 24: verify only (1 - verify, 0 - format & verify)
bit 25: head number (1=upper) bit 25: head number (1=upper)
bits 26-27: unit number (0-3) */ bits 26-27: unit number (0-3)
/* ... */ // ...
break; break;
case 10: /* load int mask case 10: // load int mask
bit 16: bad mask for interrupt (0 = unmask or enable interrupt) bit 16: bad mask for interrupt (0 = unmask or enable interrupt)
bits 17-27: 0s */ bits 17-27: 0s
m_interrupt_f_f = m_cmd_reg & 1; m_interrupt_f_f = m_cmd_reg & 1;
set_interrupt_line(); set_interrupt_line();
break; break;
case 11: /* stop case 11: // stop
bits 16-25: 0s bits 16-25: 0s
bits 26-27: unit number (0-3) */ bits 26-27: unit number (0-3)
unit = (m_cmd_reg >> 10) & 3; unit = (m_cmd_reg >> 10) & 3;
/* reset status */ // reset status
m_stat_reg = unit << status_unit_shift; m_stat_reg = unit << status_unit_shift;
m_stat_reg |= status_OP_complete; m_stat_reg |= status_OP_complete;
@ -575,10 +577,10 @@ void fd800_legacy_device::do_cmd(void)
set_interrupt_line(); set_interrupt_line();
break; break;
case 12: /* step head case 12: // step head
bits 16-22: track number (0-76) bits 16-22: track number (0-76)
bits 23-25: 0s bits 23-25: 0s
bits 26-27: unit number (0-3) */ bits 26-27: unit number (0-3)
unit = (m_cmd_reg >> 10) & 3; unit = (m_cmd_reg >> 10) & 3;
cylinder = m_cmd_reg & 0x7f; cylinder = m_cmd_reg & 0x7f;
@ -596,64 +598,64 @@ void fd800_legacy_device::do_cmd(void)
set_interrupt_line(); set_interrupt_line();
break; break;
case 13: /* maintenance commands case 13: // maintenance commands
bits 16-23: according to extended command code bits 16-23: according to extended command code
bits 24-27: extended command code (0-7) */ bits 24-27: extended command code (0-7)
switch ((m_cmd_reg >> 8) & 15) switch ((m_cmd_reg >> 8) & 15)
{ {
case 0: /* reset case 0: // reset
bits 16-23: 0s */ bits 16-23: 0s
/* ... */ // ...
break; break;
case 1: /* retry inhibit case 1: // retry inhibit
bits 16-23: 0s */ bits 16-23: 0s
/* ... */ // ...
break; break;
case 2: /* LED test case 2: // LED test
bit 16: 1 bit 16: 1
bits 17-19: 0s bits 17-19: 0s
bit 20: LED #2 enable bit 20: LED #2 enable
bit 21: LED #3 enable bit 21: LED #3 enable
bit 22: LED #4 enable bit 22: LED #4 enable
bit 23: enable LEDs */ bit 23: enable LEDs
/* ... */ // ...
break; break;
case 3: /* program error (a.k.a. invalid command) case 3: // program error (a.k.a. invalid command)
bits 16-23: 0s */ bits 16-23: 0s
/* ... */ // ...
break; break;
case 4: /* memory read case 4: // memory read
bits 16-20: controller memory address (shifted left by 8 to generate 9900 address) bits 16-20: controller memory address (shifted left by 8 to generate 9900 address)
bits 21-23: 0s */ bits 21-23: 0s
/* ... */ // ...
break; break;
case 5: /* RAM load case 5: // RAM load
bit 16: 0 bit 16: 0
bits 17-23: RAM offset (shifted left by 1 and offset by >1800 to generate 9900 address) */ bits 17-23: RAM offset (shifted left by 1 and offset by >1800 to generate 9900 address)
/* ... */ // ...
break; break;
case 6: /* RAM run case 6: // RAM run
bit 16: 0 bit 16: 0
bits 17-23: RAM offset (shifted left by 1 and offset by >1800 to generate 9900 address) */ bits 17-23: RAM offset (shifted left by 1 and offset by >1800 to generate 9900 address)
/* ... */ // ...
break; break;
case 7: /* power up simulation case 7: // power up simulation
bits 16-23: 0s */ bits 16-23: 0s
/* ... */ // ...
break; break;
} }
/* ... */ // ...
break; break;
case 14: /* IPL case 14: // IPL
bits 16-22: track number (0-76) bits 16-22: track number (0-76)
bit 23: 0 bit 23: 0
bit 24: no sequential sectoring (1=active) bit 24: no sequential sectoring (1=active)
bit 25: head number (1=upper) bit 25: head number (1=upper)
bits 26-27: unit number (0-3) */ bits 26-27: unit number (0-3)
unit = (m_cmd_reg >> 10) & 3; unit = (m_cmd_reg >> 10) & 3;
head = (m_cmd_reg >> 9) & 1; head = (m_cmd_reg >> 9) & 1;
/*non_seq_mode = (m_cmd_reg >> 8) & 1;*/ //non_seq_mode = (m_cmd_reg >> 8) & 1;
cylinder = m_cmd_reg & 0x7f; cylinder = m_cmd_reg & 0x7f;
if (!do_seek(unit, cylinder, head)) if (!do_seek(unit, cylinder, head))
@ -661,7 +663,7 @@ void fd800_legacy_device::do_cmd(void)
m_unit = unit; m_unit = unit;
m_head = head; m_head = head;
m_sector = 1; m_sector = 1;
/*m_non_seq_mode = non_seq_mode;*/ //m_non_seq_mode = non_seq_mode;
do_read(); do_read();
} }
@ -670,12 +672,13 @@ void fd800_legacy_device::do_cmd(void)
set_interrupt_line(); set_interrupt_line();
break; break;
case 15: /* Clear Status port case 15: // Clear Status port
bits 16-27: 0s */ bits 16-27: 0s
m_stat_reg = 0; m_stat_reg = 0;
set_interrupt_line(); set_interrupt_line();
break; break;
} }
*/
} }
/* /*
@ -708,13 +711,13 @@ READ8_MEMBER( fd800_legacy_device::cru_r )
{ {
case 0: case 0:
case 1: case 1:
/* receive buffer */ // receive buffer
reply = m_recv_buf >> (offset*8); reply = m_recv_buf >> (offset*8);
break; break;
case 2: case 2:
case 3: case 3:
/* status register */ // status register
reply = m_stat_reg >> ((offset-2)*8); reply = m_stat_reg >> ((offset-2)*8);
break; break;
} }
@ -754,7 +757,7 @@ WRITE8_MEMBER( fd800_legacy_device::cru_w )
case 13: case 13:
case 14: case 14:
case 15: case 15:
/* transmit buffer */ // transmit buffer
if (data) if (data)
m_xmit_buf |= 1 << offset; m_xmit_buf |= 1 << offset;
else else
@ -768,9 +771,9 @@ WRITE8_MEMBER( fd800_legacy_device::cru_w )
case bm_read: case bm_read:
m_buf_pos++; m_buf_pos++;
if (m_buf_pos == m_drv[m_unit].seclen) if (m_buf_pos == m_drv[m_unit].seclen)
{ /* end of sector */ { // end of sector
if (m_sector == 26) if (m_sector == 26)
{ /* end of track -> end command (right???) */ { // end of track -> end command (right???)
m_stat_reg &= ~status_XFER_ready; m_stat_reg &= ~status_XFER_ready;
m_stat_reg |= status_OP_complete; m_stat_reg |= status_OP_complete;
m_stat_reg |= status_interrupt; m_stat_reg |= status_interrupt;
@ -778,7 +781,7 @@ WRITE8_MEMBER( fd800_legacy_device::cru_w )
set_interrupt_line(); set_interrupt_line();
} }
else else
{ /* read next sector */ { // read next sector
m_sector++; m_sector++;
m_stat_reg &= ~status_XFER_ready | status_OP_complete | status_interrupt; m_stat_reg &= ~status_XFER_ready | status_OP_complete | status_interrupt;
do_read(); do_read();
@ -795,11 +798,11 @@ WRITE8_MEMBER( fd800_legacy_device::cru_w )
m_buf[(m_buf_pos<<1)+1] = m_xmit_buf & 0xff; m_buf[(m_buf_pos<<1)+1] = m_xmit_buf & 0xff;
m_buf_pos++; m_buf_pos++;
if (m_buf_pos == m_drv[m_unit].seclen) if (m_buf_pos == m_drv[m_unit].seclen)
{ /* end of sector */ { // end of sector
do_write(); do_write();
if (m_sector == 26) if (m_sector == 26)
{ {
/* end of track -> end command (right???) */ // end of track -> end command (right???)
m_stat_reg &= ~status_XFER_ready; m_stat_reg &= ~status_XFER_ready;
m_stat_reg |= status_OP_complete; m_stat_reg |= status_OP_complete;
m_stat_reg |= status_interrupt; m_stat_reg |= status_interrupt;
@ -807,7 +810,7 @@ WRITE8_MEMBER( fd800_legacy_device::cru_w )
set_interrupt_line(); set_interrupt_line();
} }
else else
{ /* increment to next sector */ { // increment to next sector
m_sector++; m_sector++;
m_stat_reg |= status_interrupt; m_stat_reg |= status_interrupt;
set_interrupt_line(); set_interrupt_line();
@ -834,7 +837,7 @@ WRITE8_MEMBER( fd800_legacy_device::cru_w )
case 29: case 29:
case 30: case 30:
case 31: case 31:
/* command register */ // command register
if (data) if (data)
m_cmd_reg |= 1 << (offset-16); m_cmd_reg |= 1 << (offset-16);
else else
@ -845,25 +848,25 @@ WRITE8_MEMBER( fd800_legacy_device::cru_w )
} }
} }
#if 0
LEGACY_FLOPPY_OPTIONS_START(fd800) LEGACY_FLOPPY_OPTIONS_START(fd800)
#if 1 // SSSD 8"
/* SSSD 8" */
LEGACY_FLOPPY_OPTION(fd800, "dsk", "TI990 8\" SSSD disk image", basicdsk_identify_default, basicdsk_construct_default, NULL, LEGACY_FLOPPY_OPTION(fd800, "dsk", "TI990 8\" SSSD disk image", basicdsk_identify_default, basicdsk_construct_default, NULL,
HEADS([1]) HEADS([1])
TRACKS([77]) TRACKS([77])
SECTORS([26]) SECTORS([26])
SECTOR_LENGTH([128]) SECTOR_LENGTH([128])
FIRST_SECTOR_ID([1])) FIRST_SECTOR_ID([1]))
#elif 0
/* DSSD 8" */ // DSSD 8"
LEGACY_FLOPPY_OPTION(fd800, "dsk", "TI990 8\" DSSD disk image", basicdsk_identify_default, basicdsk_construct_default, NULL, LEGACY_FLOPPY_OPTION(fd800, "dsk", "TI990 8\" DSSD disk image", basicdsk_identify_default, basicdsk_construct_default, NULL,
HEADS([2]) HEADS([2])
TRACKS([77]) TRACKS([77])
SECTORS([26]) SECTORS([26])
SECTOR_LENGTH([128]) SECTOR_LENGTH([128])
FIRST_SECTOR_ID([1])) FIRST_SECTOR_ID([1]))
#endif
LEGACY_FLOPPY_OPTIONS_END LEGACY_FLOPPY_OPTIONS_END
#endif
void fd800_legacy_device::device_start(void) void fd800_legacy_device::device_start(void)
{ {
@ -872,7 +875,7 @@ void fd800_legacy_device::device_start(void)
for (int i=0; i<MAX_FLOPPIES; i++) for (int i=0; i<MAX_FLOPPIES; i++)
{ {
m_drv[i].img = floppy_get_device(machine(), i); // m_drv[i].img = floppy_get_device(machine(), i);
m_drv[i].phys_cylinder = -1; m_drv[i].phys_cylinder = -1;
m_drv[i].log_cylinder[0] = m_drv[i].log_cylinder[1] = -1; m_drv[i].log_cylinder[0] = m_drv[i].log_cylinder[1] = -1;
m_drv[i].seclen = 64; m_drv[i].seclen = 64;

View File

@ -7,8 +7,6 @@
#ifndef __990_DK__ #ifndef __990_DK__
#define __990_DK__ #define __990_DK__
#include "imagedev/flopdrv.h"
extern const device_type FD800; extern const device_type FD800;
#define MAX_FLOPPIES 4 #define MAX_FLOPPIES 4
@ -61,14 +59,14 @@ private:
struct struct
{ {
legacy_floppy_image_device *img; // legacy_floppy_image_device *img;
int phys_cylinder; int phys_cylinder;
int log_cylinder[2]; int log_cylinder[2];
int seclen; int seclen;
} m_drv[MAX_FLOPPIES]; } m_drv[MAX_FLOPPIES];
}; };
LEGACY_FLOPPY_OPTIONS_EXTERN(fd800); // LEGACY_FLOPPY_OPTIONS_EXTERN(fd800);
#define MCFG_FD800_INT_HANDLER( _intcallb ) \ #define MCFG_FD800_INT_HANDLER( _intcallb ) \
devcb = &fd800_legacy_device::static_set_int_callback( *device, DEVCB_##_intcallb ); devcb = &fd800_legacy_device::static_set_int_callback( *device, DEVCB_##_intcallb );