summaryrefslogtreecommitdiffstatshomepage
path: root/src/mess/machine
diff options
context:
space:
mode:
author Olivier Galibert <galibert@pobox.com>2012-10-10 15:33:51 +0000
committer Olivier Galibert <galibert@pobox.com>2012-10-10 15:33:51 +0000
commit9d1aaf97ae5a4d5b2272f064fe6b6fe7df9dbf88 (patch)
tree74e3dc1e5558b42717e62f9b81cc7d7d47b90449 /src/mess/machine
parent204b78cf00de0c3bd8b6afefa601cd26aa391c91 (diff)
(mess) upd765: Modernize [O. Galibert]
Remaining TODO list: - take WP into account - test the amstrad, implement its observational format (edsk) using pasti as a start. Or find the legendary amstrad IPFs. Or both. - correct read track, the implementation is completely wrong. See previous for testing, it's only used in protections the check the inter-sector gaps. - shake and bake on the amstrad, protections are the best to find bugs in a fdc - add the scan id commands, but nothing seems to use them - debug the 2.88M formatting which is unreliable. Fix its IDAM/DAM gap size on formatting too (but that's not what's making it unreliable) - test all the systems that were hit, and fix what needs to be fixed. Beware that multiple problems may happen: - upd765 may be wrong - the driver may not be working - the hookup may be wrong/incomplete (bitrate selection and floppy rpm in particular) - the driver may be too limited for the new implementation (the x68k dma device does not handle non-instant dma yet for instance) - report invalid command when appropriate depending on the actual chip emulated - add the russian clones with their real names
Diffstat (limited to 'src/mess/machine')
-rw-r--r--src/mess/machine/amstrad.c42
-rw-r--r--src/mess/machine/apollo.c102
-rw-r--r--src/mess/machine/bebox.c69
-rw-r--r--src/mess/machine/compis.c71
-rw-r--r--src/mess/machine/fd2000.c46
-rw-r--r--src/mess/machine/fd2000.h2
-rw-r--r--src/mess/machine/genpc.c4
-rw-r--r--src/mess/machine/hec2hrp.c7
-rw-r--r--src/mess/machine/hecdisk2.c205
-rw-r--r--src/mess/machine/iq151_disc2.c49
-rw-r--r--src/mess/machine/iq151_disc2.h3
-rw-r--r--src/mess/machine/isa.h3
-rw-r--r--src/mess/machine/isa_fdc.c483
-rw-r--r--src/mess/machine/isa_fdc.h88
-rw-r--r--src/mess/machine/kc_d004.c98
-rw-r--r--src/mess/machine/kc_d004.h11
-rw-r--r--src/mess/machine/n82077aa.c1212
-rw-r--r--src/mess/machine/n82077aa.h203
-rw-r--r--src/mess/machine/pc.c50
-rw-r--r--src/mess/machine/pc_fdc.c194
-rw-r--r--src/mess/machine/pc_fdc.h79
-rw-r--r--src/mess/machine/pf10.c11
-rw-r--r--src/mess/machine/tf20.c72
-rw-r--r--src/mess/machine/upd765.c3887
-rw-r--r--src/mess/machine/upd765.h557
25 files changed, 2715 insertions, 4833 deletions
diff --git a/src/mess/machine/amstrad.c b/src/mess/machine/amstrad.c
index 14b9dbfeb2a..7ff1af47572 100644
--- a/src/mess/machine/amstrad.c
+++ b/src/mess/machine/amstrad.c
@@ -215,12 +215,9 @@ PALETTE_INIT_MEMBER(amstrad_state,amstrad_cpc_green)
}
-WRITE_LINE_MEMBER(amstrad_state::aleste_interrupt)
+void amstrad_state::aleste_interrupt(bool state)
{
- if(state == CLEAR_LINE)
- m_aleste_fdc_int = 0;
- else
- m_aleste_fdc_int = 1;
+ m_aleste_fdc_int = state;
}
@@ -1857,7 +1854,6 @@ Expansion Peripherals Read/Write - - - - - 0 - - - - - -
READ8_MEMBER(amstrad_state::amstrad_cpc_io_r)
{
- device_t *fdc = m_fdc;
mc6845_device *mc6845 = m_crtc;
unsigned char data = 0xFF;
@@ -1951,10 +1947,10 @@ The exception is the case where none of b7-b0 are reset (i.e. port &FBFF), which
switch (b8b0)
{
case 0x02:
- data = upd765_status_r(fdc, space, 0);
+ data = m_fdc->msr_r(space, 0);
break;
case 0x03:
- data = upd765_data_r(fdc, space, 0);
+ data = m_fdc->fifo_r(space, 0);
break;
default:
break;
@@ -1993,7 +1989,6 @@ void amstrad_state::amstrad_plus_seqcheck(int data)
/* Offset handler for write */
WRITE8_MEMBER(amstrad_state::amstrad_cpc_io_w)
{
- device_t *fdc = m_fdc;
mc6845_device *mc6845 = m_crtc;
cpc_multiface2_device* mface2;
@@ -2118,18 +2113,22 @@ The exception is the case where none of b7-b0 are reset (i.e. port &FBFF), which
switch (b8b0)
{
- case 0x00:
+ case 0x00: {
/* FDC Motor Control - Bit 0 defines the state of the FDD motor:
* "1" the FDD motor will be active.
* "0" the FDD motor will be in-active.*/
- floppy_mon_w(floppy_get_device(machine(), 0), !BIT(data, 0));
- floppy_mon_w(floppy_get_device(machine(), 1), !BIT(data, 0));
- floppy_drive_set_ready_state(floppy_get_device(machine(), 0), 1,1);
- floppy_drive_set_ready_state(floppy_get_device(machine(), 1), 1,1);
+ floppy_image_device *floppy;
+ floppy = machine().device<floppy_connector>(":upd765a:0")->get_device();
+ if(floppy)
+ floppy->mon_w(!BIT(data, 0));
+ floppy = machine().device<floppy_connector>(":upd765a:1")->get_device();
+ if(floppy)
+ floppy->mon_w(!BIT(data, 0));
break;
+ }
case 0x03: /* Write Data register of FDC */
- upd765_data_w(fdc, space, 0,data);
+ m_fdc->fifo_w(space, 0,data);
break;
default:
@@ -3267,16 +3266,3 @@ DEVICE_IMAGE_LOAD(amstrad_plus_cartridge)
auto_free(image.device().machine(), temp_copy);
return IMAGE_INIT_PASS;
}
-
-
-#if 0
-static DEVICE_IMAGE_LOAD( aleste )
-{
- if (device_load_basicdsk_floppy(image)==IMAGE_INIT_PASS)
- {
- basicdsk_set_geometry(image, 80, 2, 9, 512, 0x01, 0, FALSE);
- return IMAGE_INIT_PASS;
- }
- return IMAGE_INIT_FAIL;
-}
-#endif
diff --git a/src/mess/machine/apollo.c b/src/mess/machine/apollo.c
index a30c2660b0c..137ae523471 100644
--- a/src/mess/machine/apollo.c
+++ b/src/mess/machine/apollo.c
@@ -37,7 +37,8 @@
#include "machine/pic8259.h"
#include "machine/pc_fdc.h"
-#include "formats/basicdsk.h"
+#include "formats/mfi_dsk.h"
+#include "formats/apollo_dsk.h"
#include "cpu/m68000/m68000.h"
//#include "cpu/m68000/m68kcpu.h"
@@ -526,7 +527,8 @@ static WRITE8_DEVICE_HANDLER( apollo_dma8237_ctape_dack_w ) {
}
static READ8_DEVICE_HANDLER( apollo_dma8237_fdc_dack_r ) {
- UINT8 data = pc_fdc_dack_r(space.machine(), space);
+ pc_fdc_at_device *fdc = space.machine().device<pc_fdc_at_device>(APOLLO_FDC_TAG);
+ UINT8 data = fdc->dma_r();
// DLOG2(("dma fdc dack read %02x",data));
// hack for DN3000: select appropriate DMA channel No.
@@ -536,8 +538,9 @@ static READ8_DEVICE_HANDLER( apollo_dma8237_fdc_dack_r ) {
}
static WRITE8_DEVICE_HANDLER( apollo_dma8237_fdc_dack_w ) {
+ pc_fdc_at_device *fdc = space.machine().device<pc_fdc_at_device>(APOLLO_FDC_TAG);
// DLOG2(("dma fdc dack write %02x", data));
- pc_fdc_dack_w(space.machine(), space, data);
+ fdc->dma_w(data);
// hack for DN3000: select appropriate DMA channel No.
// Note: too late for this byte, but next bytes will be ok
@@ -556,8 +559,9 @@ static WRITE8_DEVICE_HANDLER( apollo_dma8237_wdc_dack_w ) {
}
static WRITE_LINE_DEVICE_HANDLER( apollo_dma8237_out_eop ) {
+ pc_fdc_at_device *fdc = device->machine().device<pc_fdc_at_device>(APOLLO_FDC_TAG);
DLOG1(("dma out eop state %02x", state));
- pc_fdc_set_tc_state(device->machine(), state ? 0 : 1);
+ fdc->tc_w(!state);
sc499_set_tc_state(&device->machine(), state);
}
@@ -1275,81 +1279,23 @@ static DEVICE_RESET(apollo_sio2)
#undef VERBOSE
#define VERBOSE 0
-static device_t *apollo_fdc_device = NULL;
-
-static LEGACY_FLOPPY_OPTIONS_START( apollo )
- LEGACY_FLOPPY_OPTION( img2d, "afd", "Apollo floppy disk image", basicdsk_identify_default, basicdsk_construct_default, NULL,
- HEADS([2])
- TRACKS([77])
- SECTORS([8])
- SECTOR_LENGTH([1024])
- FIRST_SECTOR_ID([1]))
- LEGACY_FLOPPY_OPTIONS_END0
-
-static const floppy_interface apollo_fdc_floppy_config = { //
- DEVCB_NULL, //
- DEVCB_NULL, //
- DEVCB_NULL, //
- DEVCB_NULL, //
- DEVCB_NULL, //
- FLOPPY_STANDARD_5_25_DSHD, //
- LEGACY_FLOPPY_OPTIONS_NAME(apollo), //
- NULL, //
- NULL //
+static const floppy_format_type apollo_floppy_formats[] = {
+ FLOPPY_APOLLO_FORMAT,
+ FLOPPY_MFI_FORMAT,
+ NULL
};
-/*************************************
- * Floppy Disk Controller
- *************************************/
+static SLOT_INTERFACE_START( apollo_floppies )
+ SLOT_INTERFACE( "525hd", FLOPPY_525_HD )
+SLOT_INTERFACE_END
-static void apollo_fdc_interrupt(running_machine &machine, int state) {
- apollo_pic_set_irq_line( machine.firstcpu, APOLLO_IRQ_FDC, state);
-}
-
-static void apollo_fdc_dma_drq(running_machine &machine, int state) {
- apollo_dma_fdc_drq(machine.firstcpu, state);
-}
-
-static device_t *apollo_fdc_get_image(running_machine &machine,
- int floppy_index) {
- return floppy_get_device(machine, 0);
-}
-
-static device_t * apollo_fdc_get_device(running_machine &machine) {
- return apollo_fdc_device;
-}
-
-static const struct pc_fdc_interface apollo_fdc_interface = {
- apollo_fdc_interrupt, //
- apollo_fdc_dma_drq, //
- apollo_fdc_get_image, //
- apollo_fdc_get_device //
-};
-/*-------------------------------------------------
- FDC upd765 at 0x5f800 - 0x5f807
- -------------------------------------------------*/
-
-static DEVICE_START( apollo_fdc ) {
- DLOG1(("device_start_apollo_fdc"));
- apollo_fdc_device = device;
- pc_fdc_init(device->machine(), &apollo_fdc_interface);
-}
-
-static DEVICE_RESET( apollo_fdc ) {
- DLOG1(("device_reset_apollo_fdc"));
- pc_fdc_reset(device->machine());
+void apollo_state::fdc_interrupt(bool state) {
+ apollo_pic_set_irq_line( machine().firstcpu, APOLLO_IRQ_FDC, state ? ASSERT_LINE : CLEAR_LINE);
}
-WRITE8_MEMBER(apollo_state::apollo_fdc_w){
- SLOG1(("writing FDC upd765 at offset %X = %02x", offset, data));
- pc_fdc_w(space, offset, data);
-}
-
-READ8_MEMBER(apollo_state::apollo_fdc_r){
- UINT8 data = pc_fdc_r(space, offset);
- SLOG1(("reading FDC upd765 at offset %X = %02x", offset, data));
- return data;
+void apollo_state::fdc_dma_drq(bool state) {
+ apollo_dma_fdc_drq(machine().firstcpu, state);
}
/***************************************************************************
@@ -1452,8 +1398,8 @@ MACHINE_CONFIG_FRAGMENT( apollo )
MCFG_DUART68681_ADD( APOLLO_SIO_TAG, XTAL_3_6864MHz, apollo_sio_config )
MCFG_DUART68681_ADD( APOLLO_SIO2_TAG, XTAL_3_6864MHz, apollo_sio2_config )
- MCFG_UPD765A_ADD(APOLLO_FDC_TAG, pc_fdc_upd765_connected_1_drive_interface)
- MCFG_LEGACY_FLOPPY_DRIVE_ADD(FLOPPY_0, apollo_fdc_floppy_config)
+ MCFG_PC_FDC_XT_ADD(APOLLO_FDC_TAG)
+ MCFG_FLOPPY_DRIVE_ADD(APOLLO_FDC_TAG ":0", apollo_floppies, "525hd", 0, apollo_floppy_formats)
MCFG_OMTI8621_ADD(APOLLO_WDC_TAG, apollo_wdc_config)
MCFG_SC499_ADD(APOLLO_CTAPE_TAG, apollo_ctape_config)
@@ -1469,7 +1415,10 @@ MACHINE_START_MEMBER(apollo_state,apollo)
{
//MLOG1(("machine_start_apollo"));
- device_start_apollo_fdc (machine().device(APOLLO_FDC_TAG));
+ pc_fdc_at_device *fdc = machine().device<pc_fdc_at_device>(APOLLO_FDC_TAG);
+ fdc->setup_intrq_cb(pc_fdc_at_device::line_cb(FUNC(apollo_state::fdc_interrupt), this));
+ fdc->setup_drq_cb(pc_fdc_at_device::line_cb(FUNC(apollo_state::fdc_dma_drq), this));
+
device_start_apollo_ptm (machine().device(APOLLO_PTM_TAG) );
device_start_apollo_sio(machine().device(APOLLO_SIO_TAG));
device_start_apollo_sio2(machine().device(APOLLO_SIO2_TAG));
@@ -1498,5 +1447,4 @@ MACHINE_RESET_MEMBER(apollo_state,apollo)
device_reset_apollo_rtc(machine().device(APOLLO_RTC_TAG));
device_reset_apollo_sio(machine().device(APOLLO_SIO_TAG));
device_reset_apollo_sio2(machine().device(APOLLO_SIO2_TAG));
- device_reset_apollo_fdc(apollo_fdc_device);
}
diff --git a/src/mess/machine/bebox.c b/src/mess/machine/bebox.c
index 08d87797186..1590cc19973 100644
--- a/src/mess/machine/bebox.c
+++ b/src/mess/machine/bebox.c
@@ -96,7 +96,7 @@
#include "video/cirrus.h"
#include "cpu/powerpc/ppc.h"
#include "machine/ins8250.h"
-#include "machine/pc_fdc.h"
+#include "machine/upd765.h"
#include "machine/mc146818.h"
#include "machine/pic8259.h"
#include "machine/pit8253.h"
@@ -451,47 +451,22 @@ const ins8250_interface bebox_uart_inteface_3 =
*
*************************************/
-static void bebox_fdc_interrupt(running_machine &machine, int state)
+void bebox_state::fdc_interrupt(bool state)
{
- bebox_state *drvstate = machine.driver_data<bebox_state>();
- bebox_set_irq_bit(machine, 13, state);
- if ( drvstate->m_devices.pic8259_master ) {
- pic8259_ir6_w(drvstate->m_devices.pic8259_master, state);
+ bebox_set_irq_bit(machine(), 13, state);
+ if ( m_devices.pic8259_master ) {
+ pic8259_ir6_w(m_devices.pic8259_master, state);
}
}
-static void bebox_fdc_dma_drq(running_machine &machine, int state)
+void bebox_state::fdc_dma_drq(bool state)
{
- bebox_state *drvstate = machine.driver_data<bebox_state>();
- if ( drvstate->m_devices.dma8237_1 ) {
- i8237_dreq2_w(drvstate->m_devices.dma8237_1, state);
+ if ( m_devices.dma8237_1 ) {
+ i8237_dreq2_w(m_devices.dma8237_1, state);
}
}
-
-static device_t *bebox_fdc_get_image(running_machine &machine, int floppy_index)
-{
- /* the BeBox boot ROM seems to query for floppy #1 when it should be
- * querying for floppy #0 */
- return floppy_get_device(machine, 0);
-}
-
-static device_t * bebox_get_device(running_machine &machine )
-{
- return machine.device("smc37c78");
-}
-
-
-static const struct pc_fdc_interface bebox_fdc_interface =
-{
- bebox_fdc_interrupt,
- bebox_fdc_dma_drq,
- bebox_fdc_get_image,
- bebox_get_device
-};
-
-
/*************************************
*
* 8259 PIC
@@ -563,18 +538,11 @@ WRITE8_MEMBER(bebox_state::bebox_800001F0_w ) { ide_controller_w(ide_device(spac
READ64_MEMBER(bebox_state::bebox_800003F0_r )
{
- UINT64 result = read64be_with_read8_handler(pc_fdc_r, space, offset, mem_mask | 0xFFFF);
+ UINT64 result = 0;
if (((mem_mask >> 8) & 0xFF) == 0)
{
- result &= ~(0xFF << 8);
- result |= ide_controller_r(ide_device(space.machine()), 0x3F6, 1) << 8;
- }
-
- if (((mem_mask >> 0) & 0xFF) == 0)
- {
- result &= ~(0xFF << 0);
- result |= ide_controller_r(ide_device(space.machine()), 0x3F7, 1) << 0;
+ result |= ide_controller_r(space.machine().device("ide"), 0x3F6, 1) << 8;
}
return result;
}
@@ -582,13 +550,8 @@ READ64_MEMBER(bebox_state::bebox_800003F0_r )
WRITE64_MEMBER(bebox_state::bebox_800003F0_w )
{
- write64be_with_write8_handler(pc_fdc_w, space, offset, data, mem_mask | 0xFFFF);
-
if (((mem_mask >> 8) & 0xFF) == 0)
- ide_controller_w(ide_device(space.machine()), 0x3F6, 1, (data >> 8) & 0xFF);
-
- if (((mem_mask >> 0) & 0xFF) == 0)
- ide_controller_w(ide_device(space.machine()), 0x3F7, 1, (data >> 0) & 0xFF);
+ ide_controller_w(space.machine().device("ide"), 0x3F6, 1, (data >> 8) & 0xFF);
}
@@ -768,17 +731,17 @@ WRITE8_MEMBER(bebox_state::bebox_dma_write_byte )
READ8_MEMBER(bebox_state::bebox_dma8237_fdc_dack_r){
- return pc_fdc_dack_r(machine(),space);
+ return machine().device<smc37c78_device>("smc37c78")->dma_r();
}
WRITE8_MEMBER(bebox_state::bebox_dma8237_fdc_dack_w){
- pc_fdc_dack_w( machine(), space, data );
+ machine().device<smc37c78_device>("smc37c78")->dma_w(data);
}
WRITE_LINE_MEMBER(bebox_state::bebox_dma8237_out_eop){
- pc_fdc_set_tc_state( machine(), state );
+ machine().device<smc37c78_device>("smc37c78")->tc_w(state);
}
static void set_dma_channel(running_machine &machine, int channel, int state)
@@ -1067,7 +1030,9 @@ void bebox_state::machine_reset()
void bebox_state::machine_start()
{
- pc_fdc_init(machine(), &bebox_fdc_interface);
+ smc37c78_device *fdc = machine().device<smc37c78_device>("smc37c78");
+ fdc->setup_intrq_cb(smc37c78_device::line_cb(FUNC(bebox_state::fdc_interrupt), this));
+ fdc->setup_drq_cb(smc37c78_device::line_cb(FUNC(bebox_state::fdc_dma_drq), this));
}
DRIVER_INIT_MEMBER(bebox_state,bebox)
diff --git a/src/mess/machine/compis.c b/src/mess/machine/compis.c
index 6be6779b958..eee3503983d 100644
--- a/src/mess/machine/compis.c
+++ b/src/mess/machine/compis.c
@@ -159,12 +159,7 @@ static void compis_keyb_init(compis_state *state)
/*-------------------------------------------------------------------------*/
static void compis_fdc_reset(running_machine &machine)
{
- device_t *fdc = machine.device("upd765");
-
- upd765_reset(fdc, 0);
-
- /* set FDC at reset */
- upd765_reset_w(fdc, 1);
+ machine.device("upd765")->reset();
}
void compis_state::compis_fdc_tc(int state)
@@ -172,11 +167,11 @@ void compis_state::compis_fdc_tc(int state)
/* Terminal count if iSBX-218A has DMA enabled */
if (ioport("DSW1")->read())
{
- upd765_tc_w(m_fdc, state);
+ m_fdc->tc_w(state);
}
}
-WRITE_LINE_MEMBER( compis_state::compis_fdc_int )
+void compis_state::fdc_irq(bool state)
{
/* No interrupt requests if iSBX-218A has DMA enabled */
if (!ioport("DSW1")->read() && state)
@@ -189,71 +184,15 @@ WRITE_LINE_MEMBER( compis_state::compis_fdc_int )
}
}
-WRITE_LINE_MEMBER( compis_state::compis_fdc_dma_drq )
+void compis_state::fdc_drq(bool state)
{
- /* DMA requst if iSBX-218A has DMA enabled */
+ /* DMA request if iSBX-218A has DMA enabled */
if (ioport("DSW1")->read() && state)
{
//compis_dma_drq(state, read);
}
}
-const upd765_interface compis_fdc_interface =
-{
- DEVCB_DRIVER_LINE_MEMBER(compis_state, compis_fdc_int),
- DEVCB_DRIVER_LINE_MEMBER(compis_state, compis_fdc_dma_drq),
- NULL,
- UPD765_RDY_PIN_CONNECTED,
- {FLOPPY_0, FLOPPY_1, NULL, NULL}
-};
-
-READ16_MEMBER( compis_state::compis_fdc_dack_r )
-{
- UINT16 data;
- data = 0xffff;
- /* DMA acknowledge if iSBX-218A has DMA enabled */
- if (ioport("DSW1")->read())
- {
- data = upd765_dack_r(m_fdc, space, 0);
- }
-
- return data;
-}
-
-WRITE8_MEMBER( compis_state::compis_fdc_w )
-{
- switch(offset)
- {
- case 2:
- upd765_data_w(m_fdc, space, 0, data);
- break;
- default:
- printf("FDC Unknown Port Write %04X = %04X\n", offset, data);
- break;
- }
-}
-
-READ8_MEMBER( compis_state::compis_fdc_r )
-{
- UINT16 data;
- data = 0xffff;
- switch(offset)
- {
- case 0:
- data = upd765_status_r(m_fdc, space, 0);
- break;
- case 2:
- data = upd765_data_r(m_fdc, space, 0);
- break;
- default:
- printf("FDC Unknown Port Read %04X\n", offset);
- break;
- }
-
- return data;
-}
-
-
/*-------------------------------------------------------------------------*/
/* Bit 0: J5-4 */
diff --git a/src/mess/machine/fd2000.c b/src/mess/machine/fd2000.c
index 80831949be4..a0f34dcdc3f 100644
--- a/src/mess/machine/fd2000.c
+++ b/src/mess/machine/fd2000.c
@@ -86,46 +86,14 @@ static const via6522_interface via_intf =
};
-//-------------------------------------------------
-// LEGACY_FLOPPY_OPTIONS( fd2000 )
-//-------------------------------------------------
-
-static LEGACY_FLOPPY_OPTIONS_START( fd2000 )
- LEGACY_FLOPPY_OPTION( fd2000, "d81", "Commodore 1581 Disk Image", d81_dsk_identify, d81_dsk_construct, NULL, NULL )
- //LEGACY_FLOPPY_OPTION( fd2000, "d2m", "CMD FD-2000 Disk Image", d2m_dsk_identify, d2m_dsk_construct, NULL, NULL )
-LEGACY_FLOPPY_OPTIONS_END
-
-
-//-------------------------------------------------
-// floppy_interface fd2000_floppy_interface
-//-------------------------------------------------
-
-static const floppy_interface fd2000_floppy_interface =
-{
- DEVCB_NULL,
- DEVCB_NULL,
- DEVCB_NULL,
- DEVCB_NULL,
- DEVCB_NULL,
- FLOPPY_STANDARD_3_5_DSDD,
- LEGACY_FLOPPY_OPTIONS_NAME(fd2000),
- "floppy_3_5",
+static const floppy_format_type fd2000_floppy_formats[] = {
+ FLOPPY_MFI_FORMAT,
NULL
};
-
-//-------------------------------------------------
-// upd765_interface fdc_intf
-//-------------------------------------------------
-
-static const struct upd765_interface fdc_intf =
-{
- DEVCB_NULL,
- DEVCB_NULL,
- NULL,
- UPD765_RDY_PIN_CONNECTED,
- { FLOPPY_0, NULL, NULL, NULL }
-};
+static SLOT_INTERFACE_START( fd2000_floppies )
+ SLOT_INTERFACE( "525dd", FLOPPY_525_DD )
+SLOT_INTERFACE_END
//-------------------------------------------------
@@ -137,9 +105,9 @@ static MACHINE_CONFIG_FRAGMENT( fd2000 )
MCFG_CPU_PROGRAM_MAP(fd2000_mem)
MCFG_VIA6522_ADD(M6522_TAG, 2000000, via_intf)
- MCFG_UPD765A_ADD(DP8473_TAG, fdc_intf)
+ MCFG_UPD765A_ADD(DP8473_TAG, true, true)
- MCFG_LEGACY_FLOPPY_DRIVE_ADD(FLOPPY_0, fd2000_floppy_interface)
+ MCFG_FLOPPY_DRIVE_ADD(DP8473_TAG ":0", fd2000_floppies, "525dd", 0, fd2000_floppy_formats)
MACHINE_CONFIG_END
diff --git a/src/mess/machine/fd2000.h b/src/mess/machine/fd2000.h
index 736c972c87b..89738126739 100644
--- a/src/mess/machine/fd2000.h
+++ b/src/mess/machine/fd2000.h
@@ -17,7 +17,7 @@
#include "emu.h"
#include "cpu/m6502/m6502.h"
#include "imagedev/flopdrv.h"
-#include "formats/d81_dsk.h"
+#include "formats/mfi_dsk.h"
#include "machine/6522via.h"
#include "machine/cbmiec.h"
#include "machine/upd765.h"
diff --git a/src/mess/machine/genpc.c b/src/mess/machine/genpc.c
index 3c1408a3b90..88e185e1745 100644
--- a/src/mess/machine/genpc.c
+++ b/src/mess/machine/genpc.c
@@ -527,9 +527,9 @@ static INPUT_PORTS_START( ibm5160_mb )
PORT_DIPNAME( 0x02, 0x00, "8087 installed")
PORT_DIPSETTING( 0x00, DEF_STR(No) )
PORT_DIPSETTING( 0x02, DEF_STR(Yes) )
- PORT_DIPNAME( 0x01, 0x01, "Any floppy drive installed")
- PORT_DIPSETTING( 0x00, DEF_STR(No) )
+ PORT_DIPNAME( 0x01, 0x01, "Boot from floppy")
PORT_DIPSETTING( 0x01, DEF_STR(Yes) )
+ PORT_DIPSETTING( 0x00, DEF_STR(No) )
INPUT_PORTS_END
//-------------------------------------------------
// input_ports - device-specific input ports
diff --git a/src/mess/machine/hec2hrp.c b/src/mess/machine/hec2hrp.c
index e00554b2d50..0d06168ab9d 100644
--- a/src/mess/machine/hec2hrp.c
+++ b/src/mess/machine/hec2hrp.c
@@ -45,7 +45,6 @@
#include "sound/wave.h" /* for K7 sound*/
#include "sound/discrete.h" /* for 1 Bit sound*/
#include "machine/upd765.h" /* for floppy disc controller */
-#include "formats/basicdsk.h"
#include "formats/hect_tap.h"
#include "includes/hec2hrp.h"
@@ -876,11 +875,9 @@ void hector_reset(running_machine &machine, int hr, int with_D2 )
if (with_D2==1)
{
+ upd765a_device *fdc = machine.device<upd765a_device>("upd765");
machine.device("disc2cpu")->execute().set_input_line(INPUT_LINE_RESET, PULSE_LINE);
- device_t *fdc = machine.device("upd765");
- machine.device("disc2cpu")->execute().set_input_line(INPUT_LINE_RESET, PULSE_LINE);
- upd765_reset(fdc, 1);
- upd765_reset_w(fdc, 1);
+ fdc->reset();
}
}
diff --git a/src/mess/machine/hecdisk2.c b/src/mess/machine/hecdisk2.c
index aaf28a31bb1..de9f75bb5db 100644
--- a/src/mess/machine/hecdisk2.c
+++ b/src/mess/machine/hecdisk2.c
@@ -27,14 +27,7 @@
#include "includes/hec2hrp.h"
-/* Disquette timer*/
-static TIMER_CALLBACK( Callback_DMA_irq );
-static TIMER_CALLBACK( Callback_INT_irq );
-
/* Callback uPD request */
-//UPD765_DMA_REQUEST( hector_disc2_fdc_dma_irq );
-static WRITE_LINE_DEVICE_HANDLER( disc2_fdc_interrupt );
-static WRITE_LINE_DEVICE_HANDLER( hector_disc2_fdc_dma_irq );
/* How uPD765 works:
* First we send at uPD the string of command (p.e. 9 bytes for read starting by 0x46) on port 60h
@@ -48,95 +41,29 @@ static WRITE_LINE_DEVICE_HANDLER( hector_disc2_fdc_dma_irq );
* At this point the Z80 can read the RESULT in port 61h
*/
-// Define the hardware of the disk
- const floppy_interface hector_disc2_floppy_interface =
-{
- DEVCB_NULL,
- DEVCB_NULL,
- DEVCB_NULL,
- DEVCB_NULL,
- DEVCB_NULL,
- FLOPPY_STANDARD_5_25_DSHD,
- LEGACY_FLOPPY_OPTIONS_NAME(hector_disc2),
- NULL,
- NULL
-};
-
-/*****************************************************************************/
-/****** Management of the uPD765 for interface with floppy images************/
-/*****************************************************************************/
-/* Hector Disc II uPD765 interface use interrupts and DMA! */
-const upd765_interface hector_disc2_upd765_interface =
-{
- DEVCB_LINE(disc2_fdc_interrupt),
- DEVCB_LINE(hector_disc2_fdc_dma_irq),
- NULL,
- UPD765_RDY_PIN_NOT_CONNECTED,
- {FLOPPY_0,FLOPPY_1, NULL, NULL}
-};
-
/*****************************************************************************/
/**** Management of the interrupts (NMI and INT)between uPD765 and Z80 ******/
/*****************************************************************************/
-static void valid_interrupt( running_machine &machine)
-{
- hec2hrp_state *state = machine.driver_data<hec2hrp_state>();
- /* Called at each rising state of NMI or RNMI ! */
-
- /* Take NMI only if RNMI ok*/
- if ((state->m_hector_disc2_RNMI==1) && (state->m_NMI_current_state==1))
- {
- machine.device("disc2cpu")->execute().set_input_line(INPUT_LINE_NMI, CLEAR_LINE); // Clear NMI...
- state->m_DMA_timer->adjust(attotime::from_usec(6) );//a little time to let the Z80 terminate he's previous job !
- state->m_NMI_current_state=0;
- }
-}
-
void hector_disc2_init( running_machine &machine)
{
hec2hrp_state *state = machine.driver_data<hec2hrp_state>();
- state->m_DMA_timer = machine.scheduler().timer_alloc(FUNC(Callback_DMA_irq));
- state->m_INT_timer = machine.scheduler().timer_alloc(FUNC(Callback_INT_irq));
-}
-
-static TIMER_CALLBACK( Callback_DMA_irq )
-{
- hec2hrp_state *state = machine.driver_data<hec2hrp_state>();
- /* To generate the NMI signal (late) when uPD DMA request*/
- machine.device("disc2cpu")->execute().set_input_line(INPUT_LINE_NMI, ASSERT_LINE); //NMI...
- state->m_hector_nb_cde =0; // clear the cde length
-}
-
-static TIMER_CALLBACK( Callback_INT_irq )
-{
- /* To generate the INT signal (late) when uPD DMA request*/
- /*device->*/machine.device("disc2cpu")->execute().set_input_line(INPUT_LINE_IRQ0, ASSERT_LINE);
+ upd765a_device *fdc = machine.device<upd765a_device>("upd765");
+ fdc->setup_intrq_cb(upd765a_device::line_cb(FUNC(hec2hrp_state::disc2_fdc_interrupt), state));
+ fdc->setup_drq_cb(upd765a_device::line_cb(FUNC(hec2hrp_state::disc2_fdc_dma_irq), state));
}
-/* upd765 INT is connected to interrupt of Z80 within a RNMI hardware authorization*/
-static WRITE_LINE_DEVICE_HANDLER( disc2_fdc_interrupt )
+/* upd765 INT is connected to interrupt of Z80 within a RNMI hardware authorization */
+void hec2hrp_state::disc2_fdc_interrupt(bool state)
{
- hec2hrp_state *drvstate = device->machine().driver_data<hec2hrp_state>();
- device->machine().device("disc2cpu")->execute().set_input_line(INPUT_LINE_IRQ0, CLEAR_LINE);
- if (state)
- drvstate->m_INT_timer->adjust(attotime::from_usec(500) );//a little time to let the Z80 terminate he's previous job !
+ m_IRQ_current_state = state;
+ machine().device("disc2cpu")->execute().set_input_line(INPUT_LINE_IRQ0, state && m_hector_disc2_RNMI ? ASSERT_LINE : CLEAR_LINE);
}
-static WRITE_LINE_DEVICE_HANDLER( hector_disc2_fdc_dma_irq )
+/* upd765 DRQ is connected to NMI of Z80 within a RNMI hardware authorization */
+void hec2hrp_state::disc2_fdc_dma_irq(bool state)
{
- hec2hrp_state *drvstate = device->machine().driver_data<hec2hrp_state>();
- /* upd765 DRQ is connected to NMI of Z80 within a RNMI hardware authorization*/
- /* Here the most difficult on this machine :
- The DMA request come with the uPD765 "soft" immediately,
- against the true hard uPD765. In the real life, the uPD had
- to seach for the sector before !
- So, we had to memorize the signal (the DMA is a pulse)
- until disc2's Z80 is ready to take the NMI interupt (when
- he had set the RNMI authorization) ! */
-
- if (state==1)
- drvstate->m_NMI_current_state = state;
- valid_interrupt(device->machine());
+ m_NMI_current_state = state;
+ machine().device("disc2cpu")->execute().set_input_line(INPUT_LINE_NMI, state && m_hector_disc2_RNMI ? ASSERT_LINE : CLEAR_LINE);
}
// RESET the disc2 Unit !
@@ -144,10 +71,8 @@ void hector_disc2_reset(running_machine &machine)
{
hec2hrp_state *state = machine.driver_data<hec2hrp_state>();
// Initialization Disc2 unit
- machine.device("disc2cpu" )->execute().set_input_line(INPUT_LINE_RESET, PULSE_LINE);
- //switch ON and OFF the reset line uPD
- upd765_reset_w(machine.device("upd765"), 1);
- upd765_reset_w(machine.device("upd765"), 0);
+ machine.device("disc2cpu")->execute().set_input_line(INPUT_LINE_RESET, PULSE_LINE);
+ machine.device<upd765a_device>("upd765")->reset();
// Select ROM memory to cold restart
state->membank("bank3")->set_entry(DISCII_BANK_ROM);
@@ -157,6 +82,7 @@ void hector_disc2_reset(running_machine &machine)
state->m_hector_disc2_data_read=0; /* Data send by Hector to Disc 2 when PC2=true */
state->m_hector_disc2_data_write=0; /* Data send by Disc 2 to Hector when Write Port I/O 40 */
state->m_hector_disc2_RNMI = 0; /* State of I/O 50 D5 = authorization for INT / NMI */
+ state->m_IRQ_current_state=0; /* Clear the IRQ active request */
state->m_NMI_current_state=0; /* Clear the DMA active request */
}
@@ -219,109 +145,18 @@ READ8_HANDLER( hector_disc2_io50_port_r) /*Read memory info write ready*/
WRITE8_HANDLER( hector_disc2_io50_port_w) /* I/O Port to the stuff of Disc2*/
{
hec2hrp_state *state = space.machine().driver_data<hec2hrp_state>();
- device_t *fdc = space.machine().device("upd765");
+ upd765a_device *fdc = space.machine().device<upd765a_device>("upd765");
/* FDC Motor Control - Bit 0/1 defines the state of the FDD 0/1 motor */
- floppy_mon_w(floppy_get_device(space.machine(), 0), BIT(data, 0)); // Moteur floppy A:
- floppy_mon_w(floppy_get_device(space.machine(), 1), BIT(data, 1)); // Moteur floppy B:
- floppy_drive_set_ready_state(floppy_get_device(space.machine(), 0), FLOPPY_DRIVE_READY,!BIT(data, 0));
- floppy_drive_set_ready_state(floppy_get_device(space.machine(), 1), FLOPPY_DRIVE_READY,!BIT(data, 1));
+ space.machine().device<floppy_connector>("upd765:0")->get_device()->mon_w(BIT(data, 0)); // Moteur floppy A:
+ space.machine().device<floppy_connector>("upd765:1")->get_device()->mon_w(BIT(data, 1)); // Moteur floppy B:
/* Write bit TC uPD765 on D4 of port I/O 50 */
- upd765_tc_w(fdc, BIT(data, 4)); // Seems not used...
+ fdc->tc_w(BIT(data, 4));
/* Authorization interrupt and NMI with RNMI signal*/
state->m_hector_disc2_RNMI = BIT(data, 5);
-
- /* if RNMI is OK, try to lauch an NMI*/
- if (state->m_hector_disc2_RNMI)
- valid_interrupt(space.machine());
-}
-
-//Here we must take the exchange with uPD against AM_DEVREADWRITE
-// Because we had to add D6 = 1 when write is done with 0x28 in ST0 back
-
-// AM_RANGE(0x061,0x061) AM_DEVREADWRITE("upd765",upd765_data_r,upd765_data_w)
-READ8_HANDLER( hector_disc2_io61_port_r)
-{
- hec2hrp_state *state = space.machine().driver_data<hec2hrp_state>();
- UINT8 data;
- device_t *fdc = space.machine().device("upd765");
- data = upd765_data_r(fdc,space, 0); //Get the result
-
-// if ST0 == 0x28 (drive A:) or 0x29 (drive B:) => add 0x40
-// and correct the ST1 and ST2 (patch)
- if ((state->m_hector_flag_result == 3) & ((data==0x28) | (data==0x29)) ) // are we in the problem?
- {
- data=data + 0x40;
- state->m_hector_flag_result--;
- }
- // Nothing to do in over case!
- if (state->m_hector_flag_result == 3)
- state->m_hector_flag_result = 0;
-
- if ((state->m_hector_flag_result == 2) & (data==0x00) )
- {
- data=/*data +*/ 0x04;
- state->m_hector_flag_result--;
- }
- if ((state->m_hector_flag_result == 1) & (data==0x00) )
- {
- data=/*data + */0x10;
- state->m_hector_flag_result=0; // End !
- }
- #ifdef hector_trace
- if (state->m_print==1)
- printf(" _%x",data);
- #endif
- state->m_hector_nb_cde =0; // clear the cde length
- return data;
-}
-WRITE8_HANDLER( hector_disc2_io61_port_w)
-{
- hec2hrp_state *state = space.machine().driver_data<hec2hrp_state>();
- /* Data useful to patch the RESULT in case of write command */
- state->m_hector_cmd[9]=state->m_hector_cmd[8]; //hector_cmd_8 = Cde number when state->m_hector_nb_cde = 9
- state->m_hector_cmd[8]=state->m_hector_cmd[7]; //hector_cmd_7 = Drive
- state->m_hector_cmd[7]=state->m_hector_cmd[6]; //hector_cmd_6 = C
- state->m_hector_cmd[6]=state->m_hector_cmd[5]; //hector_cmd_5 = H
- state->m_hector_cmd[5]=state->m_hector_cmd[4]; //hector_cmd_4 = R
- state->m_hector_cmd[4]=state->m_hector_cmd[3]; //hector_cmd_3 = N
- state->m_hector_cmd[3]=state->m_hector_cmd[2]; //hector_cmd_2 = EOT
- state->m_hector_cmd[2]=state->m_hector_cmd[1]; //hector_cmd_1 = GPL
- state->m_hector_cmd[1]=state->m_hector_cmd[0]; //hector_cmd_0 = DTL
- state->m_hector_cmd[0] = data;
- // Increase the length cde!
- state->m_hector_nb_cde++;
-
- // check if current commande is write cmde.
- if (((state->m_hector_cmd[8] & 0x1f)== 0x05) & (state->m_hector_nb_cde==9) ) /*Detect wrtie commande*/
- state->m_hector_flag_result = 3; // here we are!
-#ifdef hector_trace
- if (state->m_hector_nb_cde==6 ) /*Detect 1 octet command*/
- {
- printf("\n commande = %x, %x, %x, %x, %x, %x Result = ", state->m_hector_cmd[5], state->m_hector_cmd[4], state->m_hector_cmd[3], state->m_hector_cmd[2], state->m_hector_cmd[1], data );
- state->m_print=1;
- }
- else
- state->m_print=0;
-#endif
-
- device_t *fdc = space.machine().device("upd765");
- upd765_data_w(fdc,space, 0, data);
-}
-
-// AM_RANGE(0x070,0x07f) AM_DEVREADWRITE("upd765",upd765_dack_r,upd765_dack_w)
-READ8_HANDLER( hector_disc2_io70_port_r) // Gestion du DMA
-{
- UINT8 data;
- device_t *fdc = space.machine().device("upd765");
- data = upd765_dack_r(fdc,space, 0);
- return data;
-}
-WRITE8_HANDLER( hector_disc2_io70_port_w)
-{
- device_t *fdc = space.machine().device("upd765");
- upd765_dack_w(fdc,space, 0, data);
+ space.machine().device("disc2cpu")->execute().set_input_line(INPUT_LINE_IRQ0, state->m_IRQ_current_state && state->m_hector_disc2_RNMI ? ASSERT_LINE : CLEAR_LINE);
+ space.machine().device("disc2cpu")->execute().set_input_line(INPUT_LINE_NMI, state->m_NMI_current_state && state->m_hector_disc2_RNMI ? ASSERT_LINE : CLEAR_LINE);
}
diff --git a/src/mess/machine/iq151_disc2.c b/src/mess/machine/iq151_disc2.c
index 5ff4df25017..634e8893f13 100644
--- a/src/mess/machine/iq151_disc2.c
+++ b/src/mess/machine/iq151_disc2.c
@@ -6,46 +6,28 @@
#include "emu.h"
#include "iq151_disc2.h"
+#include "formats/mfi_dsk.h"
+#include "formats/iq151_dsk.h"
/***************************************************************************
IMPLEMENTATION
***************************************************************************/
-static LEGACY_FLOPPY_OPTIONS_START( iq151_disc2 )
- LEGACY_FLOPPY_OPTION( iq151_disk, "iqd", "IQ-151 disk image", basicdsk_identify_default, basicdsk_construct_default, NULL,
- HEADS([1])
- TRACKS([77])
- SECTORS([26])
- SECTOR_LENGTH([128])
- FIRST_SECTOR_ID([1]))
-LEGACY_FLOPPY_OPTIONS_END
-
-static const floppy_interface iq151_disc2_intf =
-{
- DEVCB_NULL,
- DEVCB_NULL,
- DEVCB_NULL,
- DEVCB_NULL,
- DEVCB_NULL,
- FLOPPY_STANDARD_8_SSSD,
- LEGACY_FLOPPY_OPTIONS_NAME(iq151_disc2),
- "floppy_8",
+static const floppy_format_type iq151_disc2_floppy_formats[] = {
+ FLOPPY_IQ151_FORMAT,
+ FLOPPY_MFI_FORMAT,
NULL
};
-static const upd765_interface iq151_disc2_fdc_intf =
-{
- DEVCB_NULL,
- DEVCB_NULL,
- NULL,
- UPD765_RDY_PIN_NOT_CONNECTED,
- { NULL, FLOPPY_0, FLOPPY_1, NULL }
-};
+static SLOT_INTERFACE_START( iq151_disc2_floppies )
+ SLOT_INTERFACE( "8sssd", FLOPPY_8_SSSD )
+SLOT_INTERFACE_END
static MACHINE_CONFIG_FRAGMENT( iq151_disc2 )
- MCFG_UPD72065_ADD("fdc", iq151_disc2_fdc_intf)
- MCFG_LEGACY_FLOPPY_2_DRIVES_ADD(iq151_disc2_intf)
+ MCFG_UPD72065_ADD("fdc", false, true)
+ MCFG_FLOPPY_DRIVE_ADD("fdc:1", iq151_disc2_floppies, "8sssd", 0, iq151_disc2_floppy_formats)
+ MCFG_FLOPPY_DRIVE_ADD("fdc:2", iq151_disc2_floppies, "8sssd", 0, iq151_disc2_floppy_formats)
MACHINE_CONFIG_END
ROM_START( iq151_disc2 )
@@ -129,10 +111,12 @@ void iq151_disc2_device::read(offs_t offset, UINT8 &data)
void iq151_disc2_device::io_read(offs_t offset, UINT8 &data)
{
+ /* This is gross */
+ address_space *space = NULL;
if (offset == 0xaa)
- data = upd765_status_r(m_fdc, machine().driver_data()->generic_space(), 0);
+ data = m_fdc->msr_r(*space, 0, 0xff);
else if (offset == 0xab)
- data = upd765_data_r(m_fdc, machine().driver_data()->generic_space(), 0);
+ data = m_fdc->fifo_r(*space, 0, 0xff);
}
//-------------------------------------------------
@@ -141,8 +125,9 @@ void iq151_disc2_device::io_read(offs_t offset, UINT8 &data)
void iq151_disc2_device::io_write(offs_t offset, UINT8 data)
{
+ address_space *space = NULL;
if (offset == 0xab)
- upd765_data_w(m_fdc, machine().driver_data()->generic_space(), 0, data);
+ m_fdc->fifo_w(*space, 0, data, 0xff);
else if (offset == 0xac)
m_rom_enabled = (data == 0x01);
}
diff --git a/src/mess/machine/iq151_disc2.h b/src/mess/machine/iq151_disc2.h
index 524a469775e..de62e6d4d30 100644
--- a/src/mess/machine/iq151_disc2.h
+++ b/src/mess/machine/iq151_disc2.h
@@ -6,7 +6,6 @@
#include "emu.h"
#include "machine/iq151cart.h"
#include "machine/upd765.h"
-#include "formats/basicdsk.h"
//**************************************************************************
// TYPE DEFINITIONS
@@ -39,7 +38,7 @@ protected:
private:
- required_device<device_t> m_fdc;
+ required_device<upd765a_device> m_fdc;
UINT8 * m_rom;
bool m_rom_enabled;
};
diff --git a/src/mess/machine/isa.h b/src/mess/machine/isa.h
index 3e0a8b755b8..5f7ea1b92de 100644
--- a/src/mess/machine/isa.h
+++ b/src/mess/machine/isa.h
@@ -150,6 +150,9 @@ public:
void install_device(device_t *dev, offs_t start, offs_t end, offs_t mask, offs_t mirror, read8_device_func rhandler, const char* rhandler_name, write8_device_func whandler, const char *whandler_name);
void install_device(offs_t start, offs_t end, offs_t mask, offs_t mirror, read8_delegate rhandler, write8_delegate whandler);
void install_device(offs_t start, offs_t end, offs_t mask, offs_t mirror, read8_space_func rhandler, const char* rhandler_name, write8_space_func whandler, const char *whandler_name);
+ template<typename T> void install_device(offs_t addrstart, offs_t addrend, T &device, void (T::*map)(address_map &map, device_t &device), int bits = 8, UINT64 unitmask = 0xffffffffffffffff) {
+ m_maincpu->space(AS_IO).install_device(addrstart, addrend, device, map, bits, unitmask);
+ }
void install_bank(offs_t start, offs_t end, offs_t mask, offs_t mirror, const char *tag, UINT8 *data);
void install_rom(device_t *dev, offs_t start, offs_t end, offs_t mask, offs_t mirror, const char *tag, const char *region);
void install_memory(device_t *dev, offs_t start, offs_t end, offs_t mask, offs_t mirror, read8_device_func rhandler, const char* rhandler_name, write8_device_func whandler, const char *whandler_name);
diff --git a/src/mess/machine/isa_fdc.c b/src/mess/machine/isa_fdc.c
index 98664fb9d62..bf877535adb 100644
--- a/src/mess/machine/isa_fdc.c
+++ b/src/mess/machine/isa_fdc.c
@@ -6,480 +6,159 @@
#include "emu.h"
#include "machine/isa_fdc.h"
-#include "machine/upd765.h"
+#include "machine/pc_fdc.h"
#include "imagedev/flopdrv.h"
#include "formats/pc_dsk.h"
#include "machine/idectrl.h"
+#include "formats/pc_dsk.h"
+#include "formats/mfi_dsk.h"
-static DECLARE_READ8_DEVICE_HANDLER ( pc_fdc_r );
-static DECLARE_WRITE8_DEVICE_HANDLER ( pc_fdc_w );
-
-/* if not 1, DACK and TC inputs to FDC are disabled, and DRQ and IRQ are held
- * at high impedance i.e they are not affective */
-#define PC_FDC_FLAGS_DOR_DMA_ENABLED (1<<3)
-#define PC_FDC_FLAGS_DOR_FDC_ENABLED (1<<2)
-#define PC_FDC_FLAGS_DOR_MOTOR_ON (1<<4)
-
-#define LOG_FDC 0
-static const floppy_interface ibmpc_floppy_interface =
-{
- DEVCB_NULL,
- DEVCB_NULL,
- DEVCB_NULL,
- DEVCB_NULL,
- DEVCB_NULL,
- FLOPPY_STANDARD_5_25_DSHD,
- LEGACY_FLOPPY_OPTIONS_NAME(pc),
- "floppy_5_25",
+static const floppy_format_type pc_floppy_formats[] = {
+ FLOPPY_PC_FORMAT,
+ FLOPPY_MFI_FORMAT,
NULL
};
-static WRITE_LINE_DEVICE_HANDLER( pc_fdc_hw_interrupt );
-static WRITE_LINE_DEVICE_HANDLER( pc_fdc_hw_dma_drq );
-static UPD765_GET_IMAGE ( pc_fdc_get_image );
+static SLOT_INTERFACE_START( pc_dd_floppies )
+ SLOT_INTERFACE( "525dd", FLOPPY_525_DD )
+ SLOT_INTERFACE( "35dd", FLOPPY_35_DD )
+SLOT_INTERFACE_END
-const upd765_interface pc_fdc_upd765_not_connected_interface =
-{
- DEVCB_LINE(pc_fdc_hw_interrupt),
- DEVCB_LINE(pc_fdc_hw_dma_drq),
- pc_fdc_get_image,
- UPD765_RDY_PIN_NOT_CONNECTED,
- {FLOPPY_0, FLOPPY_1, NULL, NULL}
-};
+static SLOT_INTERFACE_START( pc_hd_floppies )
+ SLOT_INTERFACE( "525hd", FLOPPY_525_HD )
+ SLOT_INTERFACE( "35hd", FLOPPY_35_HD )
+SLOT_INTERFACE_END
-static MACHINE_CONFIG_FRAGMENT( fdc_config )
- MCFG_UPD765A_ADD("upd765", pc_fdc_upd765_not_connected_interface)
-
- MCFG_LEGACY_FLOPPY_2_DRIVES_ADD(ibmpc_floppy_interface)
+static MACHINE_CONFIG_FRAGMENT( cfg_xt )
+ MCFG_PC_FDC_XT_ADD("fdc")
+ MCFG_FLOPPY_DRIVE_ADD("fdc:0", pc_dd_floppies, "525dd", 0, pc_floppy_formats)
+ MCFG_FLOPPY_DRIVE_ADD("fdc:1", pc_dd_floppies, "525dd", 0, pc_floppy_formats)
MACHINE_CONFIG_END
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
-
-const device_type ISA8_FDC = &device_creator<isa8_fdc_device>;
+static MACHINE_CONFIG_FRAGMENT( cfg_at )
+ MCFG_PC_FDC_AT_ADD("fdc")
+ MCFG_FLOPPY_DRIVE_ADD("fdc:0", pc_hd_floppies, "35hd", 0, pc_floppy_formats)
+ MCFG_FLOPPY_DRIVE_ADD("fdc:1", pc_hd_floppies, "35hd", 0, pc_floppy_formats)
+MACHINE_CONFIG_END
-//-------------------------------------------------
-// machine_config_additions - device-specific
-// machine configurations
-//-------------------------------------------------
+static MACHINE_CONFIG_FRAGMENT( cfg_smc )
+ MCFG_SMC37C78_ADD("fdc")
+ MCFG_FLOPPY_DRIVE_ADD("fdc:0", pc_hd_floppies, "35hd", 0, pc_floppy_formats)
+ MCFG_FLOPPY_DRIVE_ADD("fdc:1", pc_hd_floppies, "35hd", 0, pc_floppy_formats)
+MACHINE_CONFIG_END
-machine_config_constructor isa8_fdc_device::device_mconfig_additions() const
-{
- return MACHINE_CONFIG_NAME( fdc_config );
-}
+static MACHINE_CONFIG_FRAGMENT( cfg_ps2 )
+ MCFG_N82077AA_ADD("fdc", n82077aa_device::MODE_PS2)
+ MCFG_FLOPPY_DRIVE_ADD("fdc:0", pc_hd_floppies, "35hd", 0, pc_floppy_formats)
+ MCFG_FLOPPY_DRIVE_ADD("fdc:1", pc_hd_floppies, "35hd", 0, pc_floppy_formats)
+MACHINE_CONFIG_END
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
+static MACHINE_CONFIG_FRAGMENT( cfg_superio )
+ MCFG_PC_FDC_SUPERIO_ADD("fdc")
+ MCFG_FLOPPY_DRIVE_ADD("fdc:0", pc_hd_floppies, "35hd", 0, pc_floppy_formats)
+ MCFG_FLOPPY_DRIVE_ADD("fdc:1", pc_hd_floppies, "35hd", 0, pc_floppy_formats)
+MACHINE_CONFIG_END
-//-------------------------------------------------
-// isa8_fdc_device - constructor
-//-------------------------------------------------
-
-isa8_fdc_device::isa8_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
- device_t(mconfig, ISA8_FDC, "Diskette Drive Adapter", tag, owner, clock),
- device_isa8_card_interface(mconfig, *this),
- m_upd765(*this, "upd765")
-{
-}
isa8_fdc_device::isa8_fdc_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock) :
- device_t(mconfig, type, name, tag, owner, clock),
- device_isa8_card_interface(mconfig, *this),
- m_upd765(*this, "upd765")
+ device_t(mconfig, type, name, tag, owner, clock),
+ device_isa8_card_interface(mconfig, *this),
+ fdc(*this, "fdc")
{
}
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
void isa8_fdc_device::device_start()
{
set_isa_device();
- m_isa->install_device(this, 0x03f0, 0x03f7, 0, 0, FUNC(pc_fdc_r), FUNC(pc_fdc_w) );
+ m_isa->install_device(0x03f0, 0x03f7, *fdc, &pc_fdc_interface::map);
m_isa->set_dma_channel(2, this, TRUE);
-}
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
+ fdc->setup_intrq_cb(pc_fdc_interface::line_cb(FUNC(isa8_fdc_device::irq_w), this));
+ fdc->setup_drq_cb(pc_fdc_interface::line_cb(FUNC(isa8_fdc_device::drq_w), this));
+}
void isa8_fdc_device::device_reset()
{
- status_register_a = 0;
- status_register_b = 0;
- digital_output_register = 0;
- tape_drive_register = 0;
- data_rate_register = 2;
- digital_input_register = 0x07f;
- configuration_control_register = 0;
- tc_state = 0;
- dma_state = 0;
- int_state = 0;
-
- upd765_reset(m_upd765,0);
-
- /* set FDC at reset */
- upd765_reset_w(m_upd765, 1);
}
-static device_t *get_floppy_subdevice(device_t *device, int drive)
+void isa8_fdc_device::irq_w(bool state)
{
- switch(drive) {
- case 0 : return device->subdevice(FLOPPY_0);
- case 1 : return device->subdevice(FLOPPY_1);
- case 2 : return device->subdevice(FLOPPY_2);
- case 3 : return device->subdevice(FLOPPY_3);
- }
- return NULL;
+ m_isa->irq6_w(state ? ASSERT_LINE : CLEAR_LINE);
}
-static UPD765_GET_IMAGE ( pc_fdc_get_image )
+void isa8_fdc_device::drq_w(bool state)
{
- isa8_fdc_device *fdc = downcast<isa8_fdc_device *>(device->owner());
-
- return get_floppy_subdevice(fdc, fdc->digital_output_register & 0x03);
+ m_isa->drq2_w(state ? ASSERT_LINE : CLEAR_LINE);
}
-static WRITE_LINE_DEVICE_HANDLER( pc_fdc_set_tc_state)
+UINT8 isa8_fdc_device::dack_r(int line)
{
- isa8_fdc_device *fdc = downcast<isa8_fdc_device *>(device);
- /* store state */
- fdc->tc_state = state;
-
- /* if dma is not enabled, tc's are not acknowledged */
- if ((fdc->digital_output_register & PC_FDC_FLAGS_DOR_DMA_ENABLED)!=0)
- {
- upd765_tc_w(fdc->m_upd765, state);
- }
+ return fdc->dma_r();
}
-static WRITE_LINE_DEVICE_HANDLER( pc_fdc_hw_interrupt )
+void isa8_fdc_device::dack_w(int line, UINT8 data)
{
- isa8_fdc_device *fdc = downcast<isa8_fdc_device *>(device->owner());
-
- fdc->int_state = state;
-
- /* if dma is not enabled, irq's are masked */
- if ((fdc->digital_output_register & PC_FDC_FLAGS_DOR_DMA_ENABLED)==0)
- return;
-
- // not masked, send interrupt request
- fdc->m_isa->irq6_w(state);
+ return fdc->dma_w(data);
}
-
-static WRITE_LINE_DEVICE_HANDLER( pc_fdc_hw_dma_drq )
+void isa8_fdc_device::eop_w(int state)
{
- isa8_fdc_device *fdc = downcast<isa8_fdc_device *>(device->owner());
- fdc->dma_state = state;
-
- /* if dma is not enabled, drqs are masked */
- if ((fdc->digital_output_register & PC_FDC_FLAGS_DOR_DMA_ENABLED)==0)
- return;
-
- // not masked, send dma request
- fdc->m_isa->drq2_w(state);
+ fdc->tc_w(state == ASSERT_LINE);
}
-
-
-static WRITE8_DEVICE_HANDLER( pc_fdc_data_rate_w )
+isa8_fdc_xt_device::isa8_fdc_xt_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : isa8_fdc_device(mconfig, ISA8_FDC_XT, "ISA 8bits XT FDC hookup", tag, owner, clock)
{
- isa8_fdc_device *fdc = downcast<isa8_fdc_device *>(device);
- if ((data & 0x080)!=0)
- {
- /* set ready state */
- upd765_ready_w(fdc->m_upd765,1);
-
- /* toggle reset state */
- upd765_reset_w(fdc->m_upd765, 1);
- upd765_reset_w(fdc->m_upd765, 0);
-
- /* bit is self-clearing */
- data &= ~0x080;
- }
-
- fdc->data_rate_register = data;
+ m_shortname = "isa8_fdc_xt";
}
-
-
-/* FDC Digitial Output Register (DOR)
-
- |7|6|5|4|3|2|1|0|
- | | | | | | `------ floppy drive select (0=A, 1=B, 2=floppy C, ...)
- | | | | | `-------- 1 = FDC enable, 0 = hold FDC at reset
- | | | | `---------- 1 = DMA & I/O interface enabled
- | | | `------------ 1 = turn floppy drive A motor on
- | | `-------------- 1 = turn floppy drive B motor on
- | `---------------- 1 = turn floppy drive C motor on
- `------------------ 1 = turn floppy drive D motor on
- */
-
-static WRITE8_DEVICE_HANDLER( pc_fdc_dor_w )
+machine_config_constructor isa8_fdc_xt_device::device_mconfig_additions() const
{
- isa8_fdc_device *fdc = downcast<isa8_fdc_device *>(device);
- int selected_drive;
- int floppy_count;
-
- floppy_count = floppy_get_count(space.machine());
-
- if (floppy_count > (fdc->digital_output_register & 0x03))
- floppy_drive_set_ready_state(get_floppy_subdevice(device, fdc->digital_output_register & 0x03), 1, 0);
-
- fdc->digital_output_register = data;
-
- selected_drive = data & 0x03;
-
- /* set floppy drive motor state */
- if (floppy_count > 0)
- floppy_mon_w(get_floppy_subdevice(device, 0), !BIT(data, 4));
- if (floppy_count > 1)
- floppy_mon_w(get_floppy_subdevice(device, 1), !BIT(data, 5));
- if (floppy_count > 2)
- floppy_mon_w(get_floppy_subdevice(device, 2), !BIT(data, 6));
- if (floppy_count > 3)
- floppy_mon_w(get_floppy_subdevice(device, 3), !BIT(data, 7));
-
- if ((data>>4) & (1<<selected_drive))
- {
- if (floppy_count > selected_drive)
- floppy_drive_set_ready_state(get_floppy_subdevice(device, selected_drive), 1, 0);
- }
-
- /* changing the DMA enable bit, will affect the terminal count state
- from reaching the fdc - if dma is enabled this will send it through
- otherwise it will be ignored */
- pc_fdc_set_tc_state(device, fdc->tc_state);
-
- /* changing the DMA enable bit, will affect the dma drq state
- from reaching us - if dma is enabled this will send it through
- otherwise it will be ignored */
- pc_fdc_hw_dma_drq(fdc->m_upd765, fdc->dma_state);
-
- /* changing the DMA enable bit, will affect the irq state
- from reaching us - if dma is enabled this will send it through
- otherwise it will be ignored */
- pc_fdc_hw_interrupt(fdc->m_upd765, fdc->int_state);
-
- /* reset? */
- if ((fdc->digital_output_register & PC_FDC_FLAGS_DOR_FDC_ENABLED)==0)
- {
- /* yes */
-
- /* pc-xt expects a interrupt to be generated
- when the fdc is reset.
- In the FDC docs, it states that a INT will
- be generated if READY input is true when the
- fdc is reset.
-
- It also states, that outputs to drive are set to 0.
- Maybe this causes the drive motor to go on, and therefore
- the ready line is set.
-
- This in return causes a int?? ---
-
-
- what is not yet clear is if this is a result of the drives ready state
- changing...
- */
- upd765_ready_w(fdc->m_upd765, 1);
-
- /* set FDC at reset */
- upd765_reset_w(fdc->m_upd765, 1);
- }
- else
- {
- pc_fdc_set_tc_state(device, 0);
-
- /* release reset on fdc */
- upd765_reset_w(fdc->m_upd765, 0);
- }
+ return MACHINE_CONFIG_NAME(cfg_xt);
}
-#define RATE_250 2
-#define RATE_300 1
-#define RATE_500 0
-#define RATE_1000 3
-
-static void pc_fdc_check_data_rate(isa8_fdc_device *fdc, running_machine &machine)
+isa8_fdc_at_device::isa8_fdc_at_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : isa8_fdc_device(mconfig, ISA8_FDC_AT, "ISA 8bits AT FDC hookup", tag, owner, clock)
{
- device_t *device = get_floppy_subdevice(fdc, fdc->digital_output_register & 0x03);
- floppy_image_legacy *image;
- int tracks, sectors, rate;
-
- upd765_set_bad(fdc->m_upd765, 0); // unset in case format is unknown
- if (!device) return;
- image = flopimg_get_image(device);
- if (!image) return;
- tracks = floppy_get_tracks_per_disk(image);
- tracks -= (tracks % 10); // ignore extra tracks
- floppy_get_sector_count(image, 0, 0, &sectors);
-
- if (tracks == 40) {
- if ((fdc->data_rate_register != RATE_250) && (fdc->data_rate_register != RATE_300))
- upd765_set_bad(fdc->m_upd765, 1);
- return;
- } else if (tracks == 80) {
- if (sectors <= 14) rate = RATE_250; // 720KB 5 1/4 and 3 1/2
- else if (sectors <= 24) rate = RATE_500; // 1.2MB 5 1/4 and 1.44MB 3 1/2
- else rate = RATE_1000; // 2.88MB 3 1/2
- } else return;
-
- if (rate != (fdc->data_rate_register & 3))
- upd765_set_bad(fdc->m_upd765, 1);
+ m_shortname = "isa8_fdc_at";
}
-
-static READ8_DEVICE_HANDLER ( pc_fdc_r )
+machine_config_constructor isa8_fdc_at_device::device_mconfig_additions() const
{
- UINT8 data = 0xff;
-
- isa8_fdc_device *fdc = downcast<isa8_fdc_device *>(device);
- device_t *hdd = NULL;
- switch(offset)
- {
- case 0: /* status register a */
- case 1: /* status register b */
- data = 0x00;
- break;
- case 2:
- data = fdc->digital_output_register;
- break;
- case 3: /* tape drive select? */
- break;
- case 4:
- data = upd765_status_r(fdc->m_upd765, space, 0);
- break;
- case 5:
- data = upd765_data_r(fdc->m_upd765, space, offset);
- break;
- case 6: /* FDC reserved */
- hdd = space.machine().device(":board3:ide:ide");
- if (hdd)
- data = ide_controller16_r(hdd, space, 0x3f6/2, 0x00ff);
- break;
- case 7:
- device_t *dev = get_floppy_subdevice(device, fdc->digital_output_register & 0x03);
- data = fdc->digital_input_register;
- if(dev!=NULL) data |= (!floppy_dskchg_r(dev)<<7);
- break;
- }
-
- if (LOG_FDC)
- logerror("pc_fdc_r(): pc=0x%08x offset=%d result=0x%02X\n", (unsigned) space.machine().firstcpu->pc(), offset, data);
- return data;
+ return MACHINE_CONFIG_NAME(cfg_at);
}
-
-
-static WRITE8_DEVICE_HANDLER ( pc_fdc_w )
+isa8_fdc_smc_device::isa8_fdc_smc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : isa8_fdc_device(mconfig, ISA8_FDC_XT, "ISA 8bits SMC FDC hookup", tag, owner, clock)
{
- isa8_fdc_device *fdc = downcast<isa8_fdc_device *>(device);
-
- if (LOG_FDC)
- logerror("pc_fdc_w(): pc=0x%08x offset=%d data=0x%02X\n", (unsigned) space.machine().firstcpu->pc(), offset, data);
- pc_fdc_check_data_rate(fdc,space.machine()); // check every time a command may start
- device_t *hdd = NULL;
-
- switch(offset)
- {
- case 0: /* n/a */
- case 1: /* n/a */
- break;
- case 2:
- pc_fdc_dor_w(device, space, 0, data, mem_mask);
- break;
- case 3:
- /* tape drive select? */
- break;
- case 4:
- pc_fdc_data_rate_w(device, space, 0, data, mem_mask);
- break;
- case 5:
- upd765_data_w(fdc->m_upd765, space, 0, data);
- break;
- case 6:
- /* FDC reserved */
- hdd = space.machine().device(":board3:ide:ide");
- if (hdd)
- ide_controller16_w(hdd, space, 0x3f6/2, data, 0x00ff);
- break;
- case 7:
- /* Configuration Control Register
- *
- * Currently unimplemented; bits 1-0 are supposed to control data
- * flow rates:
- * 0 0 500 kbps
- * 0 1 300 kbps
- * 1 0 250 kbps
- * 1 1 1000 kbps
- */
- pc_fdc_data_rate_w(device, space, 0, data & 3, mem_mask);
- break;
- }
+ m_shortname = "isa8_fdc_smc";
}
-UINT8 isa8_fdc_device::dack_r(int line)
+machine_config_constructor isa8_fdc_smc_device::device_mconfig_additions() const
{
- /* what is output if dack is not acknowledged? */
- int data = 0x0ff;
-
- /* if dma is not enabled, dacks are not acknowledged */
- if ((digital_output_register & PC_FDC_FLAGS_DOR_DMA_ENABLED)!=0)
- {
- data = upd765_dack_r(m_upd765, machine().driver_data()->generic_space(), 0);
- }
-
- return data;
+ return MACHINE_CONFIG_NAME(cfg_smc);
}
-void isa8_fdc_device::dack_w(int line,UINT8 data)
+isa8_fdc_ps2_device::isa8_fdc_ps2_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : isa8_fdc_device(mconfig, ISA8_FDC_PS2, "ISA 8bits PS/2 FDC hookup", tag, owner, clock)
{
- /* if dma is not enabled, dacks are not issued */
- if ((digital_output_register & PC_FDC_FLAGS_DOR_DMA_ENABLED)!=0)
- {
- /* dma acknowledge - and send byte to fdc */
- upd765_dack_w(m_upd765, machine().driver_data()->generic_space(), 0,data);
- }
+ m_shortname = "isa8_fdc_ps2";
}
-void isa8_fdc_device::eop_w(int state)
+
+machine_config_constructor isa8_fdc_ps2_device::device_mconfig_additions() const
{
- pc_fdc_set_tc_state( this, state);
+ return MACHINE_CONFIG_NAME(cfg_ps2);
}
-static MACHINE_CONFIG_FRAGMENT( fdc_smc_config )
- MCFG_SMC37C78_ADD("upd765", pc_fdc_upd765_not_connected_interface)
-
- MCFG_LEGACY_FLOPPY_2_DRIVES_ADD(ibmpc_floppy_interface)
-MACHINE_CONFIG_END
-
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
-
-const device_type ISA8_FDC_SMC = &device_creator<isa8_fdc_smc_device>;
-
-//-------------------------------------------------
-// machine_config_additions - device-specific
-// machine configurations
-//-------------------------------------------------
-
-machine_config_constructor isa8_fdc_smc_device::device_mconfig_additions() const
+isa8_fdc_superio_device::isa8_fdc_superio_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : isa8_fdc_device(mconfig, ISA8_FDC_SUPERIO, "ISA 8bits SUPERIO FDC hookup", tag, owner, clock)
{
- return MACHINE_CONFIG_NAME( fdc_smc_config );
+ m_shortname = "isa8_fdc_superio";
}
-//-------------------------------------------------
-// isa8_fdc_smc_device - constructor
-//-------------------------------------------------
-
-isa8_fdc_smc_device::isa8_fdc_smc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
- isa8_fdc_device(mconfig, ISA8_FDC_SMC, "Diskette Drive Adapter (SMC37C78)", tag, owner, clock)
+machine_config_constructor isa8_fdc_superio_device::device_mconfig_additions() const
{
+ return MACHINE_CONFIG_NAME(cfg_superio);
}
+const device_type ISA8_FDC_XT = &device_creator<isa8_fdc_xt_device>;
+const device_type ISA8_FDC_AT = &device_creator<isa8_fdc_at_device>;
+const device_type ISA8_FDC_SMC = &device_creator<isa8_fdc_smc_device>;
+const device_type ISA8_FDC_PS2 = &device_creator<isa8_fdc_ps2_device>;
+const device_type ISA8_FDC_SUPERIO = &device_creator<isa8_fdc_superio_device>;
diff --git a/src/mess/machine/isa_fdc.h b/src/mess/machine/isa_fdc.h
index bd37f4bb968..3d251391492 100644
--- a/src/mess/machine/isa_fdc.h
+++ b/src/mess/machine/isa_fdc.h
@@ -10,6 +10,7 @@
#include "emu.h"
#include "machine/isa.h"
+#include "machine/upd765.h"
//**************************************************************************
// TYPE DEFINITIONS
@@ -18,66 +19,65 @@
// ======================> isa8_fdc_device
class isa8_fdc_device :
- public device_t,
- public device_isa8_card_interface
+ public device_t,
+ public device_isa8_card_interface
{
public:
- // construction/destruction
- isa8_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
- isa8_fdc_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
+ // construction/destruction
+ isa8_fdc_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
+
+ required_device<pc_fdc_interface> fdc;
- // optional information overrides
- virtual machine_config_constructor device_mconfig_additions() const;
protected:
- // device-level overrides
- virtual void device_start();
- virtual void device_reset();
- virtual void device_config_complete() { m_shortname = "isa_fdc"; }
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+ virtual UINT8 dack_r(int line);
+ virtual void dack_w(int line, UINT8 data);
+ virtual void eop_w(int state);
+
private:
- // internal state
-public:
- virtual UINT8 dack_r(int line);
- virtual void dack_w(int line,UINT8 data);
- virtual void eop_w(int state);
-
- int status_register_a;
- int status_register_b;
- int digital_output_register;
- int tape_drive_register;
- int data_rate_register;
- int digital_input_register;
- int configuration_control_register;
-
- /* stored tc state - state present at pins */
- int tc_state;
- /* stored dma drq state */
- int dma_state;
- /* stored int state */
- int int_state;
-
- required_device<device_t> m_upd765;
-};
+ void irq_w(bool state);
+ void drq_w(bool state);
+};
-// device type definition
-extern const device_type ISA8_FDC;
+class isa8_fdc_xt_device : public isa8_fdc_device {
+public:
+ isa8_fdc_xt_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+ virtual machine_config_constructor device_mconfig_additions() const;
+};
-// ======================> isa8_fdc_smc_device
+class isa8_fdc_at_device : public isa8_fdc_device {
+public:
+ isa8_fdc_at_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+ virtual machine_config_constructor device_mconfig_additions() const;
+};
-class isa8_fdc_smc_device :
- public isa8_fdc_device
-{
+class isa8_fdc_smc_device : public isa8_fdc_device {
public:
- // construction/destruction
- isa8_fdc_smc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+ isa8_fdc_smc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+ virtual machine_config_constructor device_mconfig_additions() const;
+};
- // optional information overrides
+class isa8_fdc_ps2_device : public isa8_fdc_device {
+public:
+ isa8_fdc_ps2_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
virtual machine_config_constructor device_mconfig_additions() const;
- virtual void device_config_complete() { m_shortname = "isa_fdc_smc"; }
};
+class isa8_fdc_superio_device : public isa8_fdc_device {
+public:
+ isa8_fdc_superio_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+ virtual machine_config_constructor device_mconfig_additions() const;
+};
// device type definition
+extern const device_type ISA8_FDC_XT;
+extern const device_type ISA8_FDC_AT;
extern const device_type ISA8_FDC_SMC;
+extern const device_type ISA8_FDC_PS2;
+extern const device_type ISA8_FDC_SUPERIO;
#endif /* ISA_FDC_H */
diff --git a/src/mess/machine/kc_d004.c b/src/mess/machine/kc_d004.c
index e570f19bd9b..6e5ab7b7c24 100644
--- a/src/mess/machine/kc_d004.c
+++ b/src/mess/machine/kc_d004.c
@@ -8,6 +8,8 @@
#include "emu.h"
#include "kc_d004.h"
+#include "formats/mfi_dsk.h"
+#include "formats/kc85_dsk.h"
#define Z80_TAG "disk"
#define Z80CTC_TAG "z80ctc"
@@ -26,9 +28,8 @@ ADDRESS_MAP_END
static ADDRESS_MAP_START(kc_d004_io, AS_IO, 8, kc_d004_device)
ADDRESS_MAP_UNMAP_HIGH
ADDRESS_MAP_GLOBAL_MASK(0xff)
- AM_RANGE(0xf0, 0xf0) AM_DEVREAD_LEGACY(UPD765_TAG, upd765_status_r)
- AM_RANGE(0xf1, 0xf1) AM_DEVREADWRITE_LEGACY(UPD765_TAG, upd765_data_r, upd765_data_w)
- AM_RANGE(0xf2, 0xf3) AM_DEVREADWRITE_LEGACY(UPD765_TAG, upd765_dack_r, upd765_dack_w)
+ AM_RANGE(0xf0, 0xf1) AM_DEVICE(UPD765_TAG, upd765a_device, map)
+ AM_RANGE(0xf2, 0xf3) AM_DEVREADWRITE(UPD765_TAG, upd765a_device, mdma_r, mdma_w)
AM_RANGE(0xf4, 0xf4) AM_READ(hw_input_gate_r)
AM_RANGE(0xf6, 0xf7) AM_WRITE(fdd_select_w)
AM_RANGE(0xf8, 0xf9) AM_WRITE(hw_terminal_count_w)
@@ -37,9 +38,8 @@ ADDRESS_MAP_END
static ADDRESS_MAP_START(kc_d004_gide_io, AS_IO, 8, kc_d004_gide_device)
ADDRESS_MAP_UNMAP_HIGH
- AM_RANGE(0x00f0, 0x00f0) AM_MIRROR(0xff00) AM_DEVREAD_LEGACY(UPD765_TAG, upd765_status_r)
- AM_RANGE(0x00f1, 0x00f1) AM_MIRROR(0xff00) AM_DEVREADWRITE_LEGACY(UPD765_TAG, upd765_data_r, upd765_data_w)
- AM_RANGE(0x00f2, 0x00f3) AM_MIRROR(0xff00) AM_DEVREADWRITE_LEGACY(UPD765_TAG, upd765_dack_r, upd765_dack_w)
+ AM_RANGE(0x00f0, 0x00f1) AM_MIRROR(0xff00) AM_DEVICE(UPD765_TAG, upd765a_device, map)
+ AM_RANGE(0x00f2, 0x00f3) AM_MIRROR(0xff00) AM_DEVREADWRITE(UPD765_TAG, upd765a_device, mdma_r, mdma_w)
AM_RANGE(0x00f4, 0x00f4) AM_MIRROR(0xff00) AM_READ(hw_input_gate_r)
AM_RANGE(0x00f6, 0x00f7) AM_MIRROR(0xff00) AM_WRITE(fdd_select_w)
AM_RANGE(0x00f8, 0x00f9) AM_MIRROR(0xff00) AM_WRITE(hw_terminal_count_w)
@@ -47,54 +47,15 @@ static ADDRESS_MAP_START(kc_d004_gide_io, AS_IO, 8, kc_d004_gide_device)
AM_RANGE(0x0000, 0xffff) AM_READWRITE(gide_r, gide_w)
ADDRESS_MAP_END
-static LEGACY_FLOPPY_OPTIONS_START(kc_d004)
- LEGACY_FLOPPY_OPTION(kc85, "img", "KC85 disk image 800KB", basicdsk_identify_default, basicdsk_construct_default, NULL,
- HEADS([2])
- TRACKS([80])
- SECTORS([5])
- SECTOR_LENGTH([1024])
- FIRST_SECTOR_ID([1]))
- LEGACY_FLOPPY_OPTION(kc85, "img", "KC85 disk image 720KB", basicdsk_identify_default, basicdsk_construct_default, NULL,
- HEADS([2])
- TRACKS([80])
- SECTORS([9])
- SECTOR_LENGTH([512])
- FIRST_SECTOR_ID([1]))
- LEGACY_FLOPPY_OPTION(kc85, "img", "KC85 disk image 640KB", basicdsk_identify_default, basicdsk_construct_default, NULL,
- HEADS([2])
- TRACKS([80])
- SECTORS([16])
- SECTOR_LENGTH([256])
- FIRST_SECTOR_ID([1]))
-LEGACY_FLOPPY_OPTIONS_END
-
-static const floppy_interface kc_d004_floppy_interface =
-{
- DEVCB_NULL,
- DEVCB_NULL,
- DEVCB_NULL,
- DEVCB_NULL,
- DEVCB_NULL,
- FLOPPY_STANDARD_5_25_DSHD,
- LEGACY_FLOPPY_OPTIONS_NAME(kc_d004),
- "floppy_5_25",
+static const floppy_format_type kc_d004_floppy_formats[] = {
+ FLOPPY_KC85_FORMAT,
+ FLOPPY_MFI_FORMAT,
NULL
};
-static device_t *kc_d004_get_fdd(device_t *device, int floppy_index)
-{
- kc_d004_device* owner = dynamic_cast<kc_d004_device *>(device->owner());
- return owner->get_active_fdd();
-}
-
-static const upd765_interface kc_d004_interface =
-{
- DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER, kc_d004_device, fdc_interrupt),
- DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER, kc_d004_device, fdc_dma_request),
- kc_d004_get_fdd,
- UPD765_RDY_PIN_NOT_CONNECTED,
- {FLOPPY_0, FLOPPY_1, FLOPPY_2, FLOPPY_3}
-};
+static SLOT_INTERFACE_START( kc_d004_floppies )
+ SLOT_INTERFACE( "525hd", FLOPPY_525_HD )
+SLOT_INTERFACE_END
static const z80_daisy_config kc_d004_daisy_chain[] =
{
@@ -118,8 +79,11 @@ static MACHINE_CONFIG_FRAGMENT(kc_d004)
MCFG_Z80CTC_ADD( Z80CTC_TAG, XTAL_8MHz/2, kc_d004_ctc_intf )
- MCFG_UPD765A_ADD(UPD765_TAG, kc_d004_interface)
- MCFG_LEGACY_FLOPPY_4_DRIVES_ADD(kc_d004_floppy_interface)
+ MCFG_UPD765A_ADD(UPD765_TAG, false, false)
+ MCFG_FLOPPY_DRIVE_ADD(UPD765_TAG ":0", kc_d004_floppies, "525hd", 0, kc_d004_floppy_formats)
+ MCFG_FLOPPY_DRIVE_ADD(UPD765_TAG ":1", kc_d004_floppies, "525hd", 0, kc_d004_floppy_formats)
+ MCFG_FLOPPY_DRIVE_ADD(UPD765_TAG ":2", kc_d004_floppies, "525hd", 0, kc_d004_floppy_formats)
+ MCFG_FLOPPY_DRIVE_ADD(UPD765_TAG ":3", kc_d004_floppies, "525hd", 0, kc_d004_floppy_formats)
MACHINE_CONFIG_END
static const ide_config ide_intf =
@@ -202,6 +166,9 @@ void kc_d004_device::device_start()
m_reset_timer = timer_alloc(TIMER_RESET);
m_tc_clear_timer = timer_alloc(TIMER_TC_CLEAR);
+
+ m_fdc->setup_intrq_cb(upd765a_device::line_cb(FUNC(kc_d004_device::fdc_irq), this));
+ m_fdc->setup_drq_cb(upd765a_device::line_cb(FUNC(kc_d004_device::fdc_drq), this));
}
//-------------------------------------------------
@@ -212,7 +179,7 @@ void kc_d004_device::device_reset()
{
m_rom_base = 0xc000;
m_enabled = m_connected = 0;
- m_floppy = downcast<device_t *>(subdevice(FLOPPY_0));
+ m_floppy = subdevice<floppy_connector>(UPD765_TAG ":0")->get_device();
// hold cpu at reset
m_reset_timer->adjust(attotime::zero);
@@ -248,7 +215,7 @@ void kc_d004_device::device_timer(emu_timer &timer, device_timer_id id, int para
m_cpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
break;
case TIMER_TC_CLEAR:
- upd765_tc_w(m_fdc, 0x00);
+ m_fdc->tc_w(false);
break;
}
}
@@ -369,12 +336,12 @@ READ8_MEMBER(kc_d004_device::hw_input_gate_r)
*/
- if (floppy_ready_r(m_floppy))
+ if (m_floppy->ready_r())
m_hw_input_gate |= 0x20;
else
m_hw_input_gate &= ~0x20;
- if (floppy_index_r(m_floppy))
+ if (m_floppy->idx_r())
m_hw_input_gate &= ~0x10;
else
m_hw_input_gate |= 0x10;
@@ -385,23 +352,26 @@ READ8_MEMBER(kc_d004_device::hw_input_gate_r)
WRITE8_MEMBER(kc_d004_device::fdd_select_w)
{
if (data & 0x01)
- m_floppy = downcast<device_t *>(subdevice(FLOPPY_0));
+ m_floppy = subdevice<floppy_connector>(UPD765_TAG ":0")->get_device();
else if (data & 0x02)
- m_floppy = downcast<device_t *>(subdevice(FLOPPY_1));
+ m_floppy = subdevice<floppy_connector>(UPD765_TAG ":1")->get_device();
else if (data & 0x04)
- m_floppy = downcast<device_t *>(subdevice(FLOPPY_2));
+ m_floppy = subdevice<floppy_connector>(UPD765_TAG ":2")->get_device();
else if (data & 0x08)
- m_floppy = downcast<device_t *>(subdevice(FLOPPY_3));
+ m_floppy = subdevice<floppy_connector>(UPD765_TAG ":3")->get_device();
+ else
+ m_floppy = NULL;
+ m_fdc->set_floppy(m_floppy);
}
WRITE8_MEMBER(kc_d004_device::hw_terminal_count_w)
{
- upd765_tc_w(m_fdc, 1);
+ m_fdc->tc_w(false);
m_tc_clear_timer->adjust(attotime::from_nsec(200));
}
-WRITE_LINE_MEMBER( kc_d004_device::fdc_interrupt )
+void kc_d004_device::fdc_irq(bool state)
{
if (state)
m_hw_input_gate &= ~0x40;
@@ -409,7 +379,7 @@ WRITE_LINE_MEMBER( kc_d004_device::fdc_interrupt )
m_hw_input_gate |= 0x40;
}
-WRITE_LINE_MEMBER( kc_d004_device::fdc_dma_request )
+void kc_d004_device::fdc_drq(bool state)
{
if (state)
m_hw_input_gate &= ~0x80;
diff --git a/src/mess/machine/kc_d004.h b/src/mess/machine/kc_d004.h
index 7d4640c4c2f..b7b376ee0dd 100644
--- a/src/mess/machine/kc_d004.h
+++ b/src/mess/machine/kc_d004.h
@@ -48,19 +48,19 @@ protected:
virtual void io_write(offs_t offset, UINT8 data);
public:
- device_t* get_active_fdd() { return m_floppy; }
DECLARE_READ8_MEMBER(hw_input_gate_r);
DECLARE_WRITE8_MEMBER(fdd_select_w);
DECLARE_WRITE8_MEMBER(hw_terminal_count_w);
- DECLARE_WRITE_LINE_MEMBER(fdc_interrupt);
- DECLARE_WRITE_LINE_MEMBER(fdc_dma_request);
+
+ void fdc_irq(bool state);
+ void fdc_drq(bool state);
private:
static const device_timer_id TIMER_RESET = 0;
static const device_timer_id TIMER_TC_CLEAR = 1;
required_device<cpu_device> m_cpu;
- required_device<device_t> m_fdc;
+ required_device<upd765a_device> m_fdc;
required_shared_ptr<UINT8> m_koppel_ram;
// internal state
@@ -73,7 +73,8 @@ private:
UINT8 m_enabled;
UINT8 m_connected;
UINT8 m_active_fdd;
- device_t * m_floppy;
+
+ floppy_image_device *m_floppy;
};
diff --git a/src/mess/machine/n82077aa.c b/src/mess/machine/n82077aa.c
deleted file mode 100644
index 5f7f96599f1..00000000000
--- a/src/mess/machine/n82077aa.c
+++ /dev/null
@@ -1,1212 +0,0 @@
-
-#include "n82077aa.h"
-
-const device_type N82077AA = &device_creator<n82077aa_device>;
-
-DEVICE_ADDRESS_MAP_START(amap, 8, n82077aa_device)
- AM_RANGE(0x0, 0x0) AM_READ(sra_r)
- AM_RANGE(0x1, 0x1) AM_READ(srb_r)
- AM_RANGE(0x2, 0x2) AM_READWRITE(dor_r, dor_w)
- AM_RANGE(0x3, 0x3) AM_READWRITE(tdr_r, tdr_w)
- AM_RANGE(0x4, 0x4) AM_READWRITE(msr_r, dsr_w)
- AM_RANGE(0x5, 0x5) AM_READWRITE(fifo_r, fifo_w)
- AM_RANGE(0x7, 0x7) AM_READWRITE(dir_r, ccr_w)
-ADDRESS_MAP_END
-
-int n82077aa_device::rates[4] = { 500000, 300000, 250000, 1000000 };
-
-n82077aa_device::n82077aa_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : device_t(mconfig, N82077AA, "N82077AA", tag, owner, clock)
-{
-}
-
-void n82077aa_device::set_mode(int _mode)
-{
- mode = _mode;
-}
-
-void n82077aa_device::setup_intrq_cb(line_cb cb)
-{
- intrq_cb = cb;
-}
-
-void n82077aa_device::setup_drq_cb(line_cb cb)
-{
- drq_cb = cb;
-}
-
-void n82077aa_device::device_start()
-{
- static const char *names[] = { "fd0", "fd1", "fd2", "fd3" };
- for(int i=0; i != 4; i++) {
- flopi[i].tm = timer_alloc(i);
- flopi[i].id = i;
- floppy_connector *con = machine().device<floppy_connector>(names[i]);
- if(con) {
- flopi[i].dev = con->get_device();
- flopi[i].dev->setup_index_pulse_cb(floppy_image_device::index_pulse_cb(FUNC(n82077aa_device::index_callback), this));
- } else
- flopi[i].dev = 0;
- }
-}
-
-void n82077aa_device::device_reset()
-{
- main_phase = PHASE_CMD;
- for(int i=0; i<4; i++) {
- flopi[i].main_state = IDLE;
- flopi[i].sub_state = IDLE;
- flopi[i].irq = false;
- flopi[i].live = false;
- }
- data_irq = false;
- dor = 0x00;
- fifo_pos = 0;
- command_pos = 0;
- result_pos = 0;
- fifocfg = 0x10;
- cur_live.fi = 0;
- cur_irq = false;
- drq = false;
- live_abort();
-}
-
-READ8_MEMBER(n82077aa_device::sra_r)
-{
- UINT8 sra = 0;
- int fid = dor & 3;
- floppy_info &fi = flopi[fid];
- if(fi.dir)
- sra |= 0x01;
- if(fi.index)
- sra |= 0x04;
- if((dsr & 3) == 0 || (dsr & 3) == 3)
- sra |= 0x08;
- if(fi.dev && fi.dev->trk00_r())
- sra |= 0x10;
- if(fi.main_state == SEEK_WAIT_STEP_SIGNAL_TIME)
- sra |= 0x20;
- sra |= 0x40;
- if(cur_irq)
- sra |= 0x80;
- if(mode == MODE_M30)
- sra ^= 0x1f;
- return sra;
-}
-
-READ8_MEMBER(n82077aa_device::srb_r)
-{
- return 0;
-}
-
-READ8_MEMBER(n82077aa_device::dor_r)
-{
- return dor;
-}
-
-WRITE8_MEMBER(n82077aa_device::dor_w)
-{
- UINT8 diff = dor ^ data;
- dor = data;
- if((diff & 4) && !(data & 4))
- device_reset();
- else
- for(int i=0; i<4; i++) {
- floppy_info &fi = flopi[i];
- if(fi.dev && (diff & (0x10 << i)))
- fi.dev->mon_w(!(dor & (0x10 << i)));
- }
-
-}
-
-READ8_MEMBER(n82077aa_device::tdr_r)
-{
- return 0;
-}
-
-WRITE8_MEMBER(n82077aa_device::tdr_w)
-{
-}
-
-READ8_MEMBER(n82077aa_device::msr_r)
-{
- UINT32 msr = 0;
- switch(main_phase) {
- case PHASE_CMD:
- msr |= 0x80;
- if(command_pos)
- msr |= 0x10;
- break;
- case PHASE_EXEC:
- msr |= 0x10;
- break;
-
- case PHASE_RESULT:
- msr |= 0xd0;
- break;
- }
- for(int i=0; i<4; i++)
- if(flopi[i].main_state == RECALIBRATE || flopi[i].main_state == SEEK)
- msr |= 1<<i;
-
- if(data_irq) {
- data_irq = false;
- check_irq();
- }
-
- return msr;
-}
-
-WRITE8_MEMBER(n82077aa_device::dsr_w)
-{
- dsr = data;
-}
-
-READ8_MEMBER(n82077aa_device::fifo_r)
-{
- UINT8 r = 0;
- switch(main_phase) {
- case PHASE_RESULT:
- r = result[0];
- result_pos--;
- memmove(result, result+1, result_pos);
- if(!result_pos)
- main_phase = PHASE_CMD;
- break;
- default:
- logerror("%s: fifo_r in phase %d\n", tag(), main_phase);
- // exit(1);
- }
-
- return r;
-}
-
-WRITE8_MEMBER(n82077aa_device::fifo_w)
-{
- switch(main_phase) {
- case PHASE_CMD: {
- command[command_pos++] = data;
- int cmd = check_command();
- if(cmd == C_INCOMPLETE)
- break;
- if(cmd == C_INVALID) {
- logerror("%s: Invalid on %02x\n", tag(), command[0]);
- exit(1);
- command_pos = 0;
- return;
- }
- start_command(cmd);
- break;
- }
- default:
- logerror("%s: fifo_w in phase %d\n", tag(), main_phase);
- exit(1);
- }
-}
-
-READ8_MEMBER(n82077aa_device::dir_r)
-{
- return 0x78;
-}
-
-WRITE8_MEMBER(n82077aa_device::ccr_w)
-{
- dsr = (dsr & 0xfc) | (data & 3);
-}
-
-void n82077aa_device::set_drq(bool state)
-{
- if(state != drq) {
- drq = state;
- if(!drq_cb.isnull())
- drq_cb(drq);
- }
-}
-
-bool n82077aa_device::get_drq() const
-{
- return drq;
-}
-
-void n82077aa_device::fifo_push(UINT8 data)
-{
- if(fifo_pos == 16) {
- logerror("%s: Overflow\n", tag());
- return;
- }
- fifo[fifo_pos++] = data;
- fifo_expected--;
- if(!drq) {
- int thr = (fifocfg & 15)+1;
- if(!fifo_expected || fifo_pos >= thr || (fifocfg & 0x20))
- set_drq(true);
- }
-}
-
-void n82077aa_device::fifo_expect(int size, bool write)
-{
- fifo_expected = size;
- fifo_write = write;
-}
-
-UINT8 n82077aa_device::dma_r()
-{
- if(!fifo_pos)
- return 0;
- UINT8 r = fifo[0];
- fifo_pos--;
- memmove(fifo, fifo+1, fifo_pos);
- if(!fifo_pos)
- set_drq(false);
- return r;
-}
-
-void n82077aa_device::live_start(floppy_info &fi, int state)
-{
- cur_live.tm = machine().time();
- cur_live.state = state;
- cur_live.next_state = -1;
- cur_live.fi = &fi;
- cur_live.shift_reg = 0;
- cur_live.crc = 0xffff;
- cur_live.bit_counter = 0;
- cur_live.data_separator_phase = false;
- cur_live.data_reg = 0;
- cur_live.previous_type = live_info::PT_NONE;
- cur_live.data_bit_context = false;
- cur_live.byte_counter = 0;
- cur_live.pll.reset(cur_live.tm);
- cur_live.pll.set_clock(attotime::from_hz(rates[dsr & 3]*2));
- checkpoint_live = cur_live;
- fi.live = true;
-
- live_run();
-}
-
-void n82077aa_device::checkpoint()
-{
- if(cur_live.fi)
- cur_live.pll.commit(cur_live.fi->dev, cur_live.tm);
- checkpoint_live = cur_live;
-}
-
-void n82077aa_device::rollback()
-{
- cur_live = checkpoint_live;
-}
-
-void n82077aa_device::live_delay(int state)
-{
- cur_live.next_state = state;
- if(cur_live.tm != machine().time())
- cur_live.fi->tm->adjust(cur_live.tm - machine().time());
-}
-
-void n82077aa_device::live_sync()
-{
- if(!cur_live.tm.is_never()) {
- if(cur_live.tm > machine().time()) {
- rollback();
- live_run(machine().time());
- cur_live.pll.commit(cur_live.fi->dev, cur_live.tm);
- }
- if(cur_live.tm == machine().time()) {
- cur_live.pll.commit(cur_live.fi->dev, cur_live.tm);
- if(cur_live.next_state != -1) {
- cur_live.state = cur_live.next_state;
- cur_live.next_state = -1;
- }
- if(cur_live.state == IDLE) {
- cur_live.tm = attotime::never;
- cur_live.fi->live = false;
- cur_live.fi = 0;
- }
- }
- cur_live.next_state = -1;
- checkpoint();
- }
-}
-
-void n82077aa_device::live_abort()
-{
-
- if(!cur_live.tm.is_never() && cur_live.tm > machine().time()) {
- rollback();
- live_run(machine().time());
- }
-
- if(cur_live.fi) {
- cur_live.pll.stop_writing(cur_live.fi->dev, cur_live.tm);
- cur_live.fi->live = false;
- cur_live.fi = 0;
- }
-
- cur_live.tm = attotime::never;
- cur_live.state = IDLE;
- cur_live.next_state = -1;
-}
-
-void n82077aa_device::live_run(attotime limit)
-{
- if(cur_live.state == IDLE || cur_live.next_state != -1)
- return;
-
- if(limit == attotime::never) {
- if(cur_live.fi->dev)
- limit = cur_live.fi->dev->time_next_index();
- if(limit == attotime::never) {
- // Happens when there's no disk or if the fdc is not
- // connected to a drive, hence no index pulse. Force a
- // sync from time to time in that case, so that the main
- // cpu timeout isn't too painful. Avoids looping into
- // infinity looking for data too.
-
- limit = machine().time() + attotime::from_msec(1);
- cur_live.fi->tm->adjust(attotime::from_msec(1));
- }
- }
-
- for(;;) {
- switch(cur_live.state) {
- case SEARCH_ADDRESS_MARK_HEADER:
- if(read_one_bit(limit))
- return;
-#if 0
- fprintf(stderr, "%s: shift = %04x data=%02x c=%d\n", tts(cur_live.tm).cstr(), cur_live.shift_reg,
- (cur_live.shift_reg & 0x4000 ? 0x80 : 0x00) |
- (cur_live.shift_reg & 0x1000 ? 0x40 : 0x00) |
- (cur_live.shift_reg & 0x0400 ? 0x20 : 0x00) |
- (cur_live.shift_reg & 0x0100 ? 0x10 : 0x00) |
- (cur_live.shift_reg & 0x0040 ? 0x08 : 0x00) |
- (cur_live.shift_reg & 0x0010 ? 0x04 : 0x00) |
- (cur_live.shift_reg & 0x0004 ? 0x02 : 0x00) |
- (cur_live.shift_reg & 0x0001 ? 0x01 : 0x00),
- cur_live.bit_counter);
-#endif
-
- if(cur_live.shift_reg == 0x4489) {
- cur_live.crc = 0x443b;
- cur_live.data_separator_phase = false;
- cur_live.bit_counter = 0;
- cur_live.state = READ_HEADER_BLOCK_HEADER;
- }
- break;
-
- case READ_HEADER_BLOCK_HEADER: {
- if(read_one_bit(limit))
- return;
-#if 0
- fprintf(stderr, "%s: shift = %04x data=%02x counter=%d\n", tts(cur_live.tm).cstr(), cur_live.shift_reg,
- (cur_live.shift_reg & 0x4000 ? 0x80 : 0x00) |
- (cur_live.shift_reg & 0x1000 ? 0x40 : 0x00) |
- (cur_live.shift_reg & 0x0400 ? 0x20 : 0x00) |
- (cur_live.shift_reg & 0x0100 ? 0x10 : 0x00) |
- (cur_live.shift_reg & 0x0040 ? 0x08 : 0x00) |
- (cur_live.shift_reg & 0x0010 ? 0x04 : 0x00) |
- (cur_live.shift_reg & 0x0004 ? 0x02 : 0x00) |
- (cur_live.shift_reg & 0x0001 ? 0x01 : 0x00),
- cur_live.bit_counter);
-#endif
- if(cur_live.bit_counter & 15)
- break;
-
- int slot = cur_live.bit_counter >> 4;
-
- if(slot < 3) {
- if(cur_live.shift_reg != 0x4489)
- cur_live.state = SEARCH_ADDRESS_MARK_HEADER;
- break;
- }
- if(cur_live.data_reg != 0xfe) {
- cur_live.state = SEARCH_ADDRESS_MARK_HEADER;
- break;
- }
-
- cur_live.bit_counter = 0;
- cur_live.state = READ_ID_BLOCK_TO_LOCAL;
-
- break;
- }
-
- case READ_ID_BLOCK_TO_LOCAL: {
- if(read_one_bit(limit))
- return;
- if(cur_live.bit_counter & 15)
- break;
- int slot = (cur_live.bit_counter >> 4)-1;
- cur_live.idbuf[slot] = cur_live.data_reg;
- if(slot == 5) {
- live_delay(IDLE);
- return;
- }
- break;
- }
-
- case SEARCH_ADDRESS_MARK_DATA:
- if(read_one_bit(limit))
- return;
-#if 0
- fprintf(stderr, "%s: shift = %04x data=%02x c=%d.%x\n", tts(cur_live.tm).cstr(), cur_live.shift_reg,
- (cur_live.shift_reg & 0x4000 ? 0x80 : 0x00) |
- (cur_live.shift_reg & 0x1000 ? 0x40 : 0x00) |
- (cur_live.shift_reg & 0x0400 ? 0x20 : 0x00) |
- (cur_live.shift_reg & 0x0100 ? 0x10 : 0x00) |
- (cur_live.shift_reg & 0x0040 ? 0x08 : 0x00) |
- (cur_live.shift_reg & 0x0010 ? 0x04 : 0x00) |
- (cur_live.shift_reg & 0x0004 ? 0x02 : 0x00) |
- (cur_live.shift_reg & 0x0001 ? 0x01 : 0x00),
- cur_live.bit_counter >> 4, cur_live.bit_counter & 15);
-#endif
- if(cur_live.bit_counter > 43*16) {
- live_delay(SEARCH_ADDRESS_MARK_DATA_FAILED);
- return;
- }
-
- if(cur_live.bit_counter >= 28*16 && cur_live.shift_reg == 0x4489) {
- cur_live.crc = 0x443b;
- cur_live.data_separator_phase = false;
- cur_live.bit_counter = 0;
- cur_live.state = READ_DATA_BLOCK_HEADER;
- }
- break;
-
- case READ_DATA_BLOCK_HEADER: {
- if(read_one_bit(limit))
- return;
-#if 0
- fprintf(stderr, "%s: shift = %04x data=%02x counter=%d\n", tts(cur_live.tm).cstr(), cur_live.shift_reg,
- (cur_live.shift_reg & 0x4000 ? 0x80 : 0x00) |
- (cur_live.shift_reg & 0x1000 ? 0x40 : 0x00) |
- (cur_live.shift_reg & 0x0400 ? 0x20 : 0x00) |
- (cur_live.shift_reg & 0x0100 ? 0x10 : 0x00) |
- (cur_live.shift_reg & 0x0040 ? 0x08 : 0x00) |
- (cur_live.shift_reg & 0x0010 ? 0x04 : 0x00) |
- (cur_live.shift_reg & 0x0004 ? 0x02 : 0x00) |
- (cur_live.shift_reg & 0x0001 ? 0x01 : 0x00),
- cur_live.bit_counter);
-#endif
- if(cur_live.bit_counter & 15)
- break;
-
- int slot = cur_live.bit_counter >> 4;
-
- if(slot < 3) {
- if(cur_live.shift_reg != 0x4489) {
- live_delay(SEARCH_ADDRESS_MARK_DATA_FAILED);
- return;
- }
- break;
- }
- if(cur_live.data_reg != 0xfb && cur_live.data_reg != 0xfd) {
- live_delay(SEARCH_ADDRESS_MARK_DATA_FAILED);
- return;
- }
-
- cur_live.bit_counter = 0;
- cur_live.state = READ_SECTOR_DATA;
- break;
- }
-
- case SEARCH_ADDRESS_MARK_DATA_FAILED:
- // status |= S_RNF;
- cur_live.state = IDLE;
- return;
-
- case READ_SECTOR_DATA: {
- if(read_one_bit(limit))
- return;
- if(cur_live.bit_counter & 15)
- break;
- int slot = (cur_live.bit_counter >> 4)-1;
- if(slot < sector_size) {
- // Sector data
- live_delay(READ_SECTOR_DATA_BYTE);
- return;
-
- } else if(slot < sector_size+2) {
- // CRC
- if(slot == sector_size+1) {
- live_delay(IDLE);
- return;
- }
- }
-
- break;
- }
-
- case READ_SECTOR_DATA_BYTE:
- fifo_push(cur_live.data_reg);
- cur_live.state = READ_SECTOR_DATA;
- checkpoint();
- break;
-
- default:
- logerror("%s: Unknown live state %d\n", tts(cur_live.tm).cstr(), cur_live.state);
- return;
- }
- }
-}
-
-int n82077aa_device::check_command()
-{
- // 0.000010 read track
- // 00000011 specify
- // 00000100 sense drive status
- // ..000101 write data
- // ...00110 read data
- // 00000111 recalibrate
- // 00001000 sense interrupt status
- // ..001001 write deleted data
- // 0.001010 read id
- // ...01100 read deleted data
- // 0.001101 format track
- // 00001110 dumpreg
- // 00001111 seek
- // 00010000 version
- // ...10001 scan equal
- // 00010010 perpendicular mode
- // 00010011 configure
- // .0010100 lock
- // ...10110 verify
- // ...11001 scan low or equal
- // ...11101 scan high or equal
- // 1.001111 relative seek
-
- switch(command[0]) {
- case 0x03:
- return command_pos == 3 ? C_SPECIFY : C_INCOMPLETE;
-
- case 0x06: case 0x26: case 0x46: case 0x66: case 0x86: case 0xa6: case 0xc6: case 0xe6:
- return command_pos == 9 ? C_READ_DATA : C_INCOMPLETE;
-
- case 0x07:
- return command_pos == 2 ? C_RECALIBRATE : C_INCOMPLETE;
-
- case 0x08:
- return C_SENSE_INTERRUPT_STATUS;
-
- case 0x0a: case 0x4a:
- return command_pos == 2 ? C_READ_ID : C_INCOMPLETE;
-
- case 0x0f:
- return command_pos == 3 ? C_SEEK : C_INCOMPLETE;
-
- case 0x12:
- return command_pos == 2 ? C_PERPENDICULAR : C_INCOMPLETE;
-
- case 0x13:
- return command_pos == 4 ? C_CONFIGURE : C_INCOMPLETE;
-
- default:
- return C_INVALID;
- }
-}
-
-void n82077aa_device::start_command(int cmd)
-{
- command_pos = 0;
- result_pos = 0;
- main_phase = PHASE_EXEC;
- switch(cmd) {
- case C_CONFIGURE:
- logerror("%s: command configure %02x %02x %02x\n",
- tag(),
- command[1], command[2], command[3]);
- // byte 1 is ignored, byte 3 is precompensation-related
- fifocfg = command[2];
- main_phase = PHASE_CMD;
- break;
-
- case C_PERPENDICULAR:
- logerror("%s: command perpendicular\n", tag());
- main_phase = PHASE_CMD;
- break;
-
- case C_READ_DATA:
- read_data_start(flopi[command[1] & 3]);
- break;
-
- case C_READ_ID:
- read_id_start(flopi[command[1] & 3]);
- break;
-
- case C_RECALIBRATE:
- recalibrate_start(flopi[command[1] & 3]);
- main_phase = PHASE_CMD;
- break;
-
- case C_SEEK:
- seek_start(flopi[command[1] & 3]);
- main_phase = PHASE_CMD;
- break;
-
- case C_SENSE_INTERRUPT_STATUS: {
- logerror("%s: command sense interrupt status\n", tag());
- main_phase = PHASE_RESULT;
-
- int fid;
- for(fid=0; fid<4 && !flopi[fid].irq; fid++);
- if(fid == 4) {
- result[0] = 0x80;
- result_pos = 1;
- break;
- }
- floppy_info &fi = flopi[fid];
- fi.irq = false;
- result[0] = (fi.status << 6) | 0x20 | fid;
- result[1] = fi.pcn;
- result_pos = 2;
- check_irq();
- break;
- }
-
- case C_SPECIFY:
- logerror("%s command specify %02x %02x\n",
- tag(),
- command[1], command[2]);
- spec = (command[1] << 8) | command[2];
- main_phase = PHASE_CMD;
- break;
-
- default:
- fprintf(stderr, "start command %d\n", cmd);
- exit(1);
- }
-}
-
-void n82077aa_device::command_end(floppy_info &fi, bool data_completion, int status)
-{
- fi.main_state = fi.sub_state = IDLE;
- if(data_completion)
- data_irq = true;
- else
- fi.irq = true;
- fi.status = status;
- check_irq();
-}
-
-void n82077aa_device::recalibrate_start(floppy_info &fi)
-{
- logerror("%s: command recalibrate\n", tag());
- fi.main_state = RECALIBRATE;
- fi.sub_state = SEEK_WAIT_STEP_TIME_DONE;
- fi.dir = 1;
- seek_continue(fi);
-}
-
-void n82077aa_device::seek_start(floppy_info &fi)
-{
- logerror("%s: command seek %d\n", tag(), command[2]);
- fi.main_state = SEEK;
- fi.sub_state = SEEK_WAIT_STEP_TIME_DONE;
- fi.dir = fi.pcn > command[2] ? 1 : 0;
- seek_continue(fi);
-}
-
-void n82077aa_device::delay_cycles(emu_timer *tm, int cycles)
-{
- tm->adjust(attotime::from_double(double(cycles)/rates[dsr & 3]));
-}
-
-void n82077aa_device::seek_continue(floppy_info &fi)
-{
- for(;;) {
- switch(fi.sub_state) {
- case SEEK_MOVE:
- if(fi.dev) {
- fi.dev->dir_w(fi.dir);
- fi.dev->stp_w(0);
- }
- fi.sub_state = SEEK_WAIT_STEP_SIGNAL_TIME;
- fi.tm->adjust(attotime::from_nsec(2500));
- return;
-
- case SEEK_WAIT_STEP_SIGNAL_TIME:
- return;
-
- case SEEK_WAIT_STEP_SIGNAL_TIME_DONE:
- if(fi.dev)
- fi.dev->stp_w(1);
-
- if(fi.main_state == SEEK) {
- if(fi.pcn > command[2])
- fi.pcn--;
- else
- fi.pcn++;
- }
- fi.sub_state = SEEK_WAIT_STEP_TIME;
- delay_cycles(fi.tm, 500*(16-(spec >> 12)));
- return;
-
- case SEEK_WAIT_STEP_TIME:
- return;
-
- case SEEK_WAIT_STEP_TIME_DONE: {
- bool done = false;
- switch(fi.main_state) {
- case RECALIBRATE:
- done = !fi.dev || !fi.dev->trk00_r();
- if(done)
- fi.pcn = 0;
- break;
- case SEEK:
- done = fi.pcn == command[2];
- break;
- }
- if(done) {
- command_end(fi, false, 0);
- return;
- }
- fi.sub_state = SEEK_MOVE;
- break;
- }
- }
- }
-}
-
-void n82077aa_device::read_data_start(floppy_info &fi)
-{
- fi.main_state = READ_DATA;
- fi.sub_state = HEAD_LOAD_DONE;
-
- logerror("%s: command read data%s%s%s cmd=%02x sel=%x chrn=(%d, %d, %d, %d) eot=%02x gpl=%02x dtl=%02x rate=%d\n",
- tag(),
- command[0] & 0x80 ? " mt" : "",
- command[0] & 0x40 ? " mfm" : "",
- command[0] & 0x20 ? " sk" : "",
- command[0],
- command[1],
- command[2],
- command[3],
- command[4],
- 128 << (command[5] & 7),
- command[6],
- command[7],
- command[8],
- rates[dsr & 3]);
-
- if(fi.dev)
- fi.dev->ss_w(command[1] & 4 ? 1 : 0);
- read_data_continue(fi);
-}
-
-void n82077aa_device::read_data_continue(floppy_info &fi)
-{
- for(;;) {
- switch(fi.sub_state) {
- case HEAD_LOAD_DONE:
- if(fi.pcn == command[2] || !(fifocfg & 0x40)) {
- fi.sub_state = SEEK_DONE;
- break;
- }
- if(fi.dev) {
- fi.dev->dir_w(fi.pcn > command[2] ? 1 : 0);
- fi.dev->stp_w(0);
- }
- fi.sub_state = SEEK_WAIT_STEP_SIGNAL_TIME;
- fi.tm->adjust(attotime::from_nsec(2500));
- return;
-
- case SEEK_WAIT_STEP_SIGNAL_TIME:
- return;
-
- case SEEK_WAIT_STEP_SIGNAL_TIME_DONE:
- if(fi.dev)
- fi.dev->stp_w(1);
-
- fi.sub_state = SEEK_WAIT_STEP_TIME;
- delay_cycles(fi.tm, 500*(16-(spec >> 12)));
- return;
-
- case SEEK_WAIT_STEP_TIME:
- return;
-
- case SEEK_WAIT_STEP_TIME_DONE:
- if(fi.pcn > command[2])
- fi.pcn--;
- else
- fi.pcn++;
- fi.sub_state = HEAD_LOAD_DONE;
- break;
-
- case SEEK_DONE:
- counter = 0;
- fi.sub_state = SCAN_ID;
- live_start(fi, SEARCH_ADDRESS_MARK_HEADER);
- return;
-
- case SCAN_ID:
- if(!sector_matches()) {
- live_start(fi, SEARCH_ADDRESS_MARK_HEADER);
- return;
- }
- if(cur_live.crc) {
- fprintf(stderr, "Header CRC error\n");
- live_start(fi, SEARCH_ADDRESS_MARK_HEADER);
- return;
- }
- sector_size = 128 << (cur_live.idbuf[3] & 3);
- fifo_expect(sector_size, false);
- fi.sub_state = SECTOR_READ;
- live_start(fi, SEARCH_ADDRESS_MARK_DATA);
- return;
-
- case SCAN_ID_FAILED:
- fprintf(stderr, "RNF\n");
- command_end(fi, true, 1);
- return;
-
- case SECTOR_READ:
- if(cur_live.crc) {
- fprintf(stderr, "CRC error\n");
- }
- if(command[4] < command[6]) {
- command[4]++;
- fi.sub_state = HEAD_LOAD_DONE;
- break;
- }
-
- main_phase = PHASE_RESULT;
- result[0] = 0;
- result[1] = 0;
- result[2] = 0;
- result[3] = command[2];
- result[4] = command[3];
- result[5] = command[4];
- result[6] = command[5];
- result_pos = 7;
- command_end(fi, true, 0);
- return;
-
- default:
- logerror("%s: read sector unknown sub-state %d\n", ttsn().cstr(), fi.sub_state);
- return;
- }
- }
-}
-
-void n82077aa_device::read_id_start(floppy_info &fi)
-{
- fi.main_state = READ_DATA;
- fi.sub_state = HEAD_LOAD_DONE;
-
- logerror("%s: command read id%s, rate=%d\n",
- tag(),
- command[0] & 0x40 ? " mfm" : "",
- rates[dsr & 3]);
-
- if(fi.dev)
- fi.dev->ss_w(command[1] & 4 ? 1 : 0);
- read_id_continue(fi);
-}
-
-void n82077aa_device::read_id_continue(floppy_info &fi)
-{
- for(;;) {
- switch(fi.sub_state) {
- case HEAD_LOAD_DONE:
- counter = 0;
- fi.sub_state = SCAN_ID;
- live_start(fi, SEARCH_ADDRESS_MARK_HEADER);
- return;
-
- case SCAN_ID:
- if(cur_live.crc) {
- fprintf(stderr, "Header CRC error\n");
- live_start(fi, SEARCH_ADDRESS_MARK_HEADER);
- return;
- }
-
- main_phase = PHASE_RESULT;
- result[0] = 0;
- result[1] = 0;
- result[2] = 0;
- result[3] = cur_live.idbuf[0];
- result[4] = cur_live.idbuf[1];
- result[5] = cur_live.idbuf[2];
- result[6] = cur_live.idbuf[3];
- result_pos = 7;
- command_end(fi, true, 0);
- return;
-
- default:
- logerror("%s: read id unknown sub-state %d\n", ttsn().cstr(), fi.sub_state);
- return;
- }
- }
-}
-
-void n82077aa_device::check_irq()
-{
- bool old_irq = cur_irq;
- cur_irq = data_irq;
- for(int i=0; i<4; i++)
- cur_irq = cur_irq || flopi[i].irq;
- if(cur_irq != old_irq && !intrq_cb.isnull())
- intrq_cb(cur_irq);
-}
-
-astring n82077aa_device::tts(attotime t)
-{
- char buf[256];
- int nsec = t.attoseconds / ATTOSECONDS_PER_NANOSECOND;
- sprintf(buf, "%4d.%03d,%03d,%03d", int(t.seconds), nsec/1000000, (nsec/1000)%1000, nsec % 1000);
- return buf;
-}
-
-astring n82077aa_device::ttsn()
-{
- return tts(machine().time());
-}
-
-void n82077aa_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
-{
- live_sync();
-
- floppy_info &fi = flopi[id];
- switch(fi.sub_state) {
- case SEEK_WAIT_STEP_SIGNAL_TIME:
- fi.sub_state = SEEK_WAIT_STEP_SIGNAL_TIME_DONE;
- break;
- case SEEK_WAIT_STEP_TIME:
- fi.sub_state = SEEK_WAIT_STEP_TIME_DONE;
- break;
- }
-
- general_continue(fi);
-}
-
-void n82077aa_device::index_callback(floppy_image_device *floppy, int state)
-{
- int fid;
- for(fid=0; fid<4; fid++)
- if(flopi[fid].dev == floppy)
- break;
-
- assert(fid != 4);
- floppy_info &fi = flopi[fid];
-
- live_sync();
- fi.index = state;
-
- if(!state) {
- general_continue(fi);
- return;
- }
-
- switch(fi.sub_state) {
- case IDLE:
- case SEEK_MOVE:
- case SEEK_WAIT_STEP_SIGNAL_TIME:
- case SEEK_WAIT_STEP_SIGNAL_TIME_DONE:
- case SEEK_WAIT_STEP_TIME:
- case SEEK_WAIT_STEP_TIME_DONE:
- case HEAD_LOAD_DONE:
- case SCAN_ID_FAILED:
- case SECTOR_READ:
- break;
-
- case SCAN_ID:
- counter++;
- if(counter == 2)
- fi.sub_state = SCAN_ID_FAILED;
- break;
-
- default:
- logerror("%s: Index pulse on unknown sub-state %d\n", ttsn().cstr(), fi.sub_state);
- break;
- }
-
- general_continue(fi);
-}
-
-
-void n82077aa_device::general_continue(floppy_info &fi)
-{
- if(fi.live && cur_live.state != IDLE) {
- live_run();
- if(cur_live.state != IDLE)
- return;
- }
-
- switch(fi.main_state) {
- case IDLE:
- break;
-
- case RECALIBRATE:
- case SEEK:
- seek_continue(fi);
- break;
-
- case READ_DATA:
- read_data_continue(fi);
- break;
-
- case READ_ID:
- read_id_continue(fi);
- break;
-
- default:
- logerror("%s: general_continue on unknown main-state %d\n", ttsn().cstr(), fi.main_state);
- break;
- }
-}
-
-bool n82077aa_device::read_one_bit(attotime limit)
-{
- int bit = cur_live.pll.get_next_bit(cur_live.tm, cur_live.fi->dev, limit);
- if(bit < 0)
- return true;
- cur_live.shift_reg = (cur_live.shift_reg << 1) | bit;
- cur_live.bit_counter++;
- if(cur_live.data_separator_phase) {
- cur_live.data_reg = (cur_live.data_reg << 1) | bit;
- if((cur_live.crc ^ (bit ? 0x8000 : 0x0000)) & 0x8000)
- cur_live.crc = (cur_live.crc << 1) ^ 0x1021;
- else
- cur_live.crc = cur_live.crc << 1;
- }
- cur_live.data_separator_phase = !cur_live.data_separator_phase;
- return false;
-}
-
-bool n82077aa_device::write_one_bit(attotime limit)
-{
- bool bit = cur_live.shift_reg & 0x8000;
- if(cur_live.pll.write_next_bit(bit, cur_live.tm, cur_live.fi->dev, limit))
- return true;
- if(cur_live.bit_counter & 1) {
- if((cur_live.crc ^ (bit ? 0x8000 : 0x0000)) & 0x8000)
- cur_live.crc = (cur_live.crc << 1) ^ 0x1021;
- else
- cur_live.crc = cur_live.crc << 1;
- }
- cur_live.shift_reg = cur_live.shift_reg << 1;
- cur_live.bit_counter--;
- return false;
-}
-
-bool n82077aa_device::sector_matches() const
-{
- return
- cur_live.idbuf[0] == command[2] &&
- cur_live.idbuf[1] == command[3] &&
- cur_live.idbuf[2] == command[4] &&
- cur_live.idbuf[3] == command[5];
-}
-
-void n82077aa_device::pll_t::set_clock(attotime _period)
-{
- period = _period;
- period_adjust_base = period * 0.05;
- min_period = period * 0.75;
- max_period = period * 1.25;
-}
-
-void n82077aa_device::pll_t::reset(attotime when)
-{
- ctime = when;
- phase_adjust = attotime::zero;
- freq_hist = 0;
- write_position = 0;
- write_start_time = attotime::never;
-}
-
-void n82077aa_device::pll_t::start_writing(attotime tm)
-{
- write_start_time = tm;
- write_position = 0;
-}
-
-void n82077aa_device::pll_t::stop_writing(floppy_image_device *floppy, attotime tm)
-{
- commit(floppy, tm);
- write_start_time = attotime::never;
-}
-
-void n82077aa_device::pll_t::commit(floppy_image_device *floppy, attotime tm)
-{
- if(write_start_time.is_never() || tm == write_start_time)
- return;
-
- if(floppy)
- floppy->write_flux(write_start_time, tm, write_position, write_buffer);
- write_start_time = tm;
- write_position = 0;
-}
-
-int n82077aa_device::pll_t::get_next_bit(attotime &tm, floppy_image_device *floppy, attotime limit)
-{
- attotime edge = floppy ? floppy->get_next_transition(ctime) : attotime::never;
-
- attotime next = ctime + period + phase_adjust;
-
-#if 0
- if(!edge.is_never())
- fprintf(stderr, "transition_time=%s, next=%s\n", tts(edge).cstr(), tts(next).cstr());
-#endif
-
- if(next > limit)
- return -1;
-
- ctime = next;
-
- if(edge.is_never() || edge >= next) {
- // No transition in the window means 0 and pll in free run mode
- phase_adjust = attotime::zero;
- tm = next;
- return 0;
- }
-
- // Transition in the window means 1, and the pll is adjusted
-
- attotime delta = edge - (next - period/2);
-
- phase_adjust = 0.65*delta;
-
- if(delta < attotime::zero) {
- if(freq_hist < 0)
- freq_hist--;
- else
- freq_hist = -1;
- } else if(delta > attotime::zero) {
- if(freq_hist > 0)
- freq_hist++;
- else
- freq_hist = 1;
- } else
- freq_hist = 0;
-
- if(freq_hist) {
- int afh = freq_hist < 0 ? -freq_hist : freq_hist;
- if(afh > 1) {
- attotime aper = attotime::from_double(period_adjust_base.as_double()*delta.as_double()/period.as_double());
- period += aper;
-
- if(period < min_period)
- period = min_period;
- else if(period > max_period)
- period = max_period;
- }
- }
-
- return 1;
-}
-
-bool n82077aa_device::pll_t::write_next_bit(bool bit, attotime &tm, floppy_image_device *floppy, attotime limit)
-{
- if(write_start_time.is_never()) {
- write_start_time = ctime;
- write_position = 0;
- }
-
- attotime etime = ctime + period;
- if(etime > limit)
- return true;
-
- if(write_position < ARRAY_LENGTH(write_buffer))
- write_buffer[write_position++] = ctime + period/2;
-
- tm = etime;
- ctime = etime;
- return false;
-}
diff --git a/src/mess/machine/n82077aa.h b/src/mess/machine/n82077aa.h
deleted file mode 100644
index 0e045a3202d..00000000000
--- a/src/mess/machine/n82077aa.h
+++ /dev/null
@@ -1,203 +0,0 @@
-#ifndef __N82077AA_H__
-#define __N82077AA_H__
-
-#include "emu.h"
-#include "imagedev/floppy.h"
-
-#define MCFG_N82077AA_ADD(_tag, _mode) \
- MCFG_DEVICE_ADD(_tag, N82077AA, 0) \
- downcast<n82077aa_device *>(device)->set_mode(_mode);
-
-class n82077aa_device : public device_t {
-public:
- typedef delegate<void (bool state)> line_cb;
-
- enum { MODE_AT, MODE_PS2, MODE_M30 };
-
- n82077aa_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
- void set_mode(int mode);
- void setup_intrq_cb(line_cb cb);
- void setup_drq_cb(line_cb cb);
-
- DECLARE_ADDRESS_MAP(amap, 8);
-
- DECLARE_READ8_MEMBER (sra_r);
- DECLARE_READ8_MEMBER (srb_r);
- DECLARE_READ8_MEMBER (dor_r);
- DECLARE_WRITE8_MEMBER(dor_w);
- DECLARE_READ8_MEMBER (tdr_r);
- DECLARE_WRITE8_MEMBER(tdr_w);
- DECLARE_READ8_MEMBER (msr_r);
- DECLARE_WRITE8_MEMBER(dsr_w);
- DECLARE_READ8_MEMBER (fifo_r);
- DECLARE_WRITE8_MEMBER(fifo_w);
- DECLARE_READ8_MEMBER (dir_r);
- DECLARE_WRITE8_MEMBER(ccr_w);
-
- UINT8 dma_r();
- void dma_w(UINT8 data);
- bool get_drq() const;
-
-protected:
- virtual void device_start();
- virtual void device_reset();
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
-
-private:
- enum {
- PHASE_CMD, PHASE_EXEC, PHASE_RESULT
- };
-
- enum {
- // General "doing nothing" state
- IDLE,
-
- // Main states
- RECALIBRATE,
- SEEK,
- READ_DATA,
- READ_ID,
-
- // Sub-states
- SEEK_MOVE,
- SEEK_WAIT_STEP_SIGNAL_TIME,
- SEEK_WAIT_STEP_SIGNAL_TIME_DONE,
- SEEK_WAIT_STEP_TIME,
- SEEK_WAIT_STEP_TIME_DONE,
- SEEK_DONE,
-
- HEAD_LOAD_DONE,
-
- SCAN_ID,
- SCAN_ID_FAILED,
-
- SECTOR_READ,
-
- // Live states
- SEARCH_ADDRESS_MARK_HEADER,
- READ_HEADER_BLOCK_HEADER,
- READ_DATA_BLOCK_HEADER,
- READ_ID_BLOCK_TO_LOCAL,
- SEARCH_ADDRESS_MARK_DATA,
- SEARCH_ADDRESS_MARK_DATA_FAILED,
- READ_SECTOR_DATA,
- READ_SECTOR_DATA_BYTE,
-
- };
-
- struct pll_t {
- attotime ctime, period, min_period, max_period, period_adjust_base, phase_adjust;
-
- attotime write_start_time;
- attotime write_buffer[32];
- int write_position;
- int freq_hist;
-
- void set_clock(attotime period);
- void reset(attotime when);
- int get_next_bit(attotime &tm, floppy_image_device *floppy, attotime limit);
- bool write_next_bit(bool bit, attotime &tm, floppy_image_device *floppy, attotime limit);
- void start_writing(attotime tm);
- void commit(floppy_image_device *floppy, attotime tm);
- void stop_writing(floppy_image_device *floppy, attotime tm);
- };
-
- struct floppy_info {
- emu_timer *tm;
- floppy_image_device *dev;
- int id;
- int main_state, sub_state;
- int dir, status;
- UINT8 pcn;
- bool irq, live, index;
- };
-
- struct live_info {
- enum { PT_NONE, PT_CRC_1, PT_CRC_2 };
-
- attotime tm;
- int state, next_state;
- floppy_info *fi;
- UINT16 shift_reg;
- UINT16 crc;
- int bit_counter, byte_counter, previous_type;
- bool data_separator_phase, data_bit_context;
- UINT8 data_reg;
- UINT8 idbuf[6];
- pll_t pll;
- };
-
- static int rates[4];
-
- int mode;
- int main_phase;
- int counter;
-
- live_info cur_live, checkpoint_live;
- line_cb intrq_cb, drq_cb;
- bool cur_irq, data_irq, drq;
- floppy_info flopi[4];
-
- int fifo_pos, fifo_expected, command_pos, result_pos;
- bool fifo_write;
- UINT8 dor, dsr, msr, fifo[16], command[16], result[16];
- UINT8 fifocfg;
- UINT16 spec;
- int sector_size;
-
- static astring tts(attotime t);
- astring ttsn();
-
- enum {
- C_CONFIGURE,
- C_PERPENDICULAR,
- C_READ_DATA,
- C_READ_ID,
- C_RECALIBRATE,
- C_SEEK,
- C_SENSE_INTERRUPT_STATUS,
- C_SPECIFY,
-
- C_INVALID,
- C_INCOMPLETE,
- };
-
- void delay_cycles(emu_timer *tm, int cycles);
- void check_irq();
- void fifo_expect(int size, bool write);
- void fifo_push(UINT8 data);
- void set_drq(bool state);
-
- int check_command();
- void start_command(int cmd);
- void command_end(floppy_info &fi, bool data_completion, int status);
-
- void recalibrate_start(floppy_info &fi);
- void seek_start(floppy_info &fi);
- void seek_continue(floppy_info &fi);
-
- void read_data_start(floppy_info &fi);
- void read_data_continue(floppy_info &fi);
-
- void read_id_start(floppy_info &fi);
- void read_id_continue(floppy_info &fi);
-
- void general_continue(floppy_info &fi);
- void index_callback(floppy_image_device *floppy, int state);
- bool sector_matches() const;
-
- void live_start(floppy_info &fi, int live_state);
- void live_abort();
- void checkpoint();
- void rollback();
- void live_delay(int state);
- void live_sync();
- void live_run(attotime limit = attotime::never);
-
- bool read_one_bit(attotime limit);
- bool write_one_bit(attotime limit);
-};
-
-extern const device_type N82077AA;
-
-#endif
diff --git a/src/mess/machine/pc.c b/src/mess/machine/pc.c
index d24e2cac56b..ef62505961e 100644
--- a/src/mess/machine/pc.c
+++ b/src/mess/machine/pc.c
@@ -202,7 +202,7 @@ WRITE8_MEMBER(pc_state::pc_dma_write_byte)
READ8_MEMBER(pc_state::pc_dma8237_fdc_dack_r)
{
- return pc_fdc_dack_r(machine(), space);
+ return machine().device<pc_fdc_interface>("fdc")->dma_r();
}
@@ -214,7 +214,7 @@ READ8_MEMBER(pc_state::pc_dma8237_hdc_dack_r)
WRITE8_MEMBER(pc_state::pc_dma8237_fdc_dack_w)
{
- pc_fdc_dack_w( machine(), space, data );
+ machine().device<pc_fdc_interface>("fdc")->dma_w(data);
}
@@ -232,7 +232,7 @@ WRITE8_MEMBER(pc_state::pc_dma8237_0_dack_w)
WRITE_LINE_MEMBER(pc_state::pc_dma8237_out_eop)
{
- pc_fdc_set_tc_state( machine(), state == ASSERT_LINE ? 0 : 1 );
+ machine().device<pc_fdc_interface>("fdc")->tc_w(state == ASSERT_LINE);
}
static void set_dma_channel(running_machine &machine, int channel, int state)
@@ -1136,44 +1136,19 @@ I8255_INTERFACE( mc1502_ppi8255_interface_2 )
*
**********************************************************/
-static void pc_fdc_interrupt(running_machine &machine, int state)
+void pc_state::fdc_interrupt(bool state)
{
- pc_state *st = machine.driver_data<pc_state>();
- if (st->m_pic8259)
+ if (m_pic8259)
{
- pic8259_ir6_w(st->m_pic8259, state);
+ pic8259_ir6_w(m_pic8259, state);
}
}
-static void pc_fdc_dma_drq(running_machine &machine, int state)
+void pc_state::fdc_dma_drq(bool state)
{
- pc_state *st = machine.driver_data<pc_state>();
- i8237_dreq2_w( st->m_dma8237, state);
+ i8237_dreq2_w( m_dma8237, state);
}
-static device_t * pc_get_device(running_machine &machine )
-{
- return machine.device("upd765");
-}
-
-static const struct pc_fdc_interface fdc_interface_nc =
-{
- pc_fdc_interrupt,
- pc_fdc_dma_drq,
- NULL,
- pc_get_device
-};
-
-
-static const struct pc_fdc_interface pcjr_fdc_interface_nc =
-{
- pc_fdc_interrupt,
- NULL,
- NULL,
- pc_get_device
-};
-
-
static void pc_set_irq_line(running_machine &machine,int irq, int state)
{
pc_state *st = machine.driver_data<pc_state>();
@@ -1396,7 +1371,10 @@ MACHINE_START_MEMBER(pc_state,pc)
m_pic8259 = machine().device("pic8259");
m_dma8237 = machine().device("dma8237");
m_pit8253 = machine().device("pit8253");
- pc_fdc_init( machine(), &fdc_interface_nc );
+
+ pc_fdc_interface *fdc = machine().device<pc_fdc_interface>("fdc");
+ fdc->setup_intrq_cb(pc_fdc_interface::line_cb(FUNC(pc_state::fdc_interrupt), this));
+ fdc->setup_drq_cb(pc_fdc_interface::line_cb(FUNC(pc_state::fdc_dma_drq), this));
}
@@ -1450,8 +1428,8 @@ MACHINE_START_MEMBER(pc_state,mc1502)
MACHINE_START_MEMBER(pc_state,pcjr)
{
- pc_fdc_init( machine(), &pcjr_fdc_interface_nc );
- pcjr_keyb.keyb_signal_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(pc_state::pcjr_keyb_signal_callback),this));
+ pc_fdc_interface *fdc = machine().device<pc_fdc_interface>("fdc");
+ fdc->setup_intrq_cb(pc_fdc_interface::line_cb(FUNC(pc_state::fdc_interrupt), this));
pc_int_delay_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(pc_state::pcjr_delayed_pic8259_irq),this));
m_maincpu = machine().device<cpu_device>("maincpu" );
m_maincpu->set_irq_acknowledge_callback(pc_irq_callback);
diff --git a/src/mess/machine/pc_fdc.c b/src/mess/machine/pc_fdc.c
index 9a6a33cbbde..3c7570ed9be 100644
--- a/src/mess/machine/pc_fdc.c
+++ b/src/mess/machine/pc_fdc.c
@@ -13,7 +13,198 @@
#include "emu.h"
#include "machine/pc_fdc.h"
-#include "machine/upd765.h"
+
+const device_type PC_FDC_XT = &device_creator<pc_fdc_xt_device>;
+const device_type PC_FDC_AT = &device_creator<pc_fdc_at_device>;
+const device_type PC_FDC_JR = &device_creator<pc_fdc_jr_device>;
+
+static MACHINE_CONFIG_FRAGMENT( cfg )
+ MCFG_UPD765A_ADD("upd765", false, false)
+MACHINE_CONFIG_END
+
+DEVICE_ADDRESS_MAP_START(map, 8, pc_fdc_family_device)
+ADDRESS_MAP_END
+
+// The schematics show address decoding is minimal
+DEVICE_ADDRESS_MAP_START(map, 8, pc_fdc_xt_device)
+ AM_RANGE(0x0, 0x0) AM_DEVREAD("upd765", upd765a_device, msr_r) AM_WRITE(dor_w)
+ AM_RANGE(0x1, 0x1) AM_DEVREAD("upd765", upd765a_device, fifo_r) AM_WRITE(dor_fifo_w)
+ AM_RANGE(0x2, 0x2) AM_WRITE(dor_w)
+ AM_RANGE(0x3, 0x3) AM_WRITE(dor_w)
+ AM_RANGE(0x4, 0x5) AM_DEVICE("upd765", upd765a_device, map)
+ADDRESS_MAP_END
+
+
+// Decoding is through a PAL, so presumably complete
+DEVICE_ADDRESS_MAP_START(map, 8, pc_fdc_at_device)
+ AM_RANGE(0x2, 0x2) AM_READWRITE(dor_r, dor_w)
+ AM_RANGE(0x4, 0x5) AM_DEVICE("upd765", upd765a_device, map)
+ AM_RANGE(0x7, 0x7) AM_READWRITE(dir_r, ccr_w)
+ADDRESS_MAP_END
+
+
+
+pc_fdc_family_device::pc_fdc_family_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock) : pc_fdc_interface(mconfig, type, name, tag, owner, clock), fdc(*this, "upd765")
+{
+}
+
+void pc_fdc_family_device::setup_intrq_cb(line_cb cb)
+{
+ intrq_cb = cb;
+}
+
+void pc_fdc_family_device::setup_drq_cb(line_cb cb)
+{
+ drq_cb = cb;
+}
+
+void pc_fdc_family_device::tc_w(bool state)
+{
+ fdc->tc_w(state);
+}
+
+UINT8 pc_fdc_family_device::dma_r()
+{
+ return fdc->dma_r();
+}
+
+void pc_fdc_family_device::dma_w(UINT8 data)
+{
+ fdc->dma_w(data);
+}
+
+machine_config_constructor pc_fdc_family_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME(cfg);
+}
+
+void pc_fdc_family_device::device_start()
+{
+ fdc->setup_intrq_cb(upd765a_device::line_cb(FUNC(pc_fdc_family_device::irq_w), this));
+ fdc->setup_drq_cb(upd765a_device::line_cb(FUNC(pc_fdc_family_device::drq_w), this));
+
+ for(int i=0; i<4; i++) {
+ char name[2] = {'0'+i, 0};
+ floppy_connector *conn = subdevice<floppy_connector>(name);
+ floppy[i] = conn ? conn->get_device() : NULL;
+ }
+
+ irq = drq = false;
+ fdc_irq = fdc_drq = false;
+ dor = 0x00;
+}
+
+void pc_fdc_family_device::device_reset()
+{
+}
+
+// Bits 0-1 select one of the 4 drives, but only if the associated
+// motor bit is on
+
+// Bit 2 is tied to the upd765 reset line
+
+// Bit 3 enables the irq and drq lines
+
+// Bit 4-7 control the drive motors
+
+WRITE8_MEMBER( pc_fdc_family_device::dor_w )
+{
+ logerror("%s: dor = %02x\n", tag(), data);
+ UINT8 pdor = dor;
+ dor = data;
+
+ for(int i=0; i<4; i++)
+ if(floppy[i])
+ floppy[i]->mon_w(!(dor & (0x10 << i)));
+
+ int fid = dor & 3;
+ if(dor & (0x10 << fid))
+ fdc->set_floppy(floppy[fid]);
+ else
+ fdc->set_floppy(NULL);
+
+ check_irq();
+ check_drq();
+ if((pdor^dor) & 4)
+ fdc->reset();
+}
+
+READ8_MEMBER( pc_fdc_family_device::dor_r )
+{
+ return dor;
+}
+
+READ8_MEMBER( pc_fdc_family_device::dir_r )
+{
+ return do_dir_r();
+}
+
+WRITE8_MEMBER( pc_fdc_family_device::ccr_w )
+{
+ static const int rates[4] = { 500000, 300000, 250000, 1000000 };
+ logerror("%s: ccr = %02x\n", tag(), data);
+ fdc->set_rate(rates[data & 3]);
+}
+
+UINT8 pc_fdc_family_device::do_dir_r()
+{
+ if(floppy[dor & 3])
+ return floppy[dor & 3]->dskchg_r() ? 0x00 : 0x80;
+ return 0x00;
+}
+
+WRITE8_MEMBER( pc_fdc_xt_device::dor_fifo_w)
+{
+ fdc->fifo_w(space, 0, data, mem_mask);
+ dor_w(space, 0, data, mem_mask);
+}
+
+void pc_fdc_family_device::irq_w(bool state)
+{
+ fdc_irq = state;
+ check_irq();
+}
+
+void pc_fdc_family_device::drq_w(bool state)
+{
+ fdc_drq = state;
+ check_drq();
+}
+
+void pc_fdc_family_device::check_irq()
+{
+ bool pirq = irq;
+ irq = fdc_irq && (dor & 4) && (dor & 8);
+ if(irq != pirq && !intrq_cb.isnull()) {
+ logerror("%s: pc_irq = %d\n", tag(), irq);
+ intrq_cb(irq);
+ }
+}
+
+void pc_fdc_family_device::check_drq()
+{
+ bool pdrq = drq;
+ drq = fdc_drq && (dor & 4) && (dor & 8);
+ if(drq != pdrq && !drq_cb.isnull())
+ drq_cb(drq);
+}
+
+pc_fdc_xt_device::pc_fdc_xt_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : pc_fdc_family_device(mconfig, PC_FDC_XT, "PC FDC XT", tag, owner, clock)
+{
+ m_shortname = "pc_fdc_xt";
+}
+
+pc_fdc_at_device::pc_fdc_at_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : pc_fdc_family_device(mconfig, PC_FDC_AT, "PC FDC AT", tag, owner, clock)
+{
+ m_shortname = "pc_fdc_at";
+}
+
+pc_fdc_jr_device::pc_fdc_jr_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : pc_fdc_family_device(mconfig, PC_FDC_JR, "PC FDC JR", tag, owner, clock)
+{
+ m_shortname = "pc_fdc_jr";
+}
+
+#if 0
/* if not 1, DACK and TC inputs to FDC are disabled, and DRQ and IRQ are held
@@ -579,3 +770,4 @@ WRITE8_HANDLER ( pcjr_fdc_w )
}
}
+#endif
diff --git a/src/mess/machine/pc_fdc.h b/src/mess/machine/pc_fdc.h
index a5b32975a9a..e812b5ac6a2 100644
--- a/src/mess/machine/pc_fdc.h
+++ b/src/mess/machine/pc_fdc.h
@@ -8,8 +8,84 @@
#define PC_FDC_H
#include "emu.h"
-#include "machine/upd765.h"
+#include "imagedev/floppy.h"
+#include "upd765.h"
+#define MCFG_PC_FDC_XT_ADD(_tag) \
+ MCFG_DEVICE_ADD(_tag, PC_FDC_XT, 0)
+
+#define MCFG_PC_FDC_AT_ADD(_tag) \
+ MCFG_DEVICE_ADD(_tag, PC_FDC_AT, 0)
+
+#define MCFG_PC_FDC_JR_ADD(_tag) \
+ MCFG_DEVICE_ADD(_tag, PC_FDC_JR, 0)
+
+
+class pc_fdc_family_device : public pc_fdc_interface {
+public:
+ pc_fdc_family_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
+
+ required_device<upd765a_device> fdc;
+
+ virtual void setup_intrq_cb(line_cb cb);
+ virtual void setup_drq_cb(line_cb cb);
+
+ virtual DECLARE_ADDRESS_MAP(map, 8);
+
+ virtual void tc_w(bool state);
+ virtual UINT8 dma_r();
+ virtual void dma_w(UINT8 data);
+ virtual UINT8 do_dir_r();
+
+ READ8_MEMBER(dor_r);
+ WRITE8_MEMBER(dor_w);
+ READ8_MEMBER(dir_r);
+ WRITE8_MEMBER(ccr_w);
+
+protected:
+ virtual void device_start();
+ virtual void device_reset();
+ virtual machine_config_constructor device_mconfig_additions() const;
+
+ line_cb intrq_cb, drq_cb;
+ bool irq, drq, fdc_drq, fdc_irq;
+ UINT8 dor;
+
+ floppy_image_device *floppy[4];
+
+ void irq_w(bool state);
+ void drq_w(bool state);
+ void check_irq();
+ void check_drq();
+};
+
+class pc_fdc_xt_device : public pc_fdc_family_device {
+public:
+ pc_fdc_xt_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ virtual DECLARE_ADDRESS_MAP(map, 8);
+ WRITE8_MEMBER(dor_fifo_w);
+};
+
+class pc_fdc_at_device : public pc_fdc_family_device {
+public:
+ pc_fdc_at_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ virtual DECLARE_ADDRESS_MAP(map, 8);
+};
+
+class pc_fdc_jr_device : public pc_fdc_family_device {
+public:
+ pc_fdc_jr_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+};
+
+
+extern const device_type PC_FDC_XT;
+extern const device_type PC_FDC_AT;
+extern const device_type PC_FDC_JR;
+
+
+#if 0
/* interface has been seperated, so that it can be used in the super i/o chip */
#define PC_FDC_STATUS_REGISTER_A 0
@@ -47,6 +123,7 @@ DECLARE_READ8_HANDLER(pc_fdc_r);
DECLARE_WRITE8_HANDLER(pc_fdc_w);
DECLARE_WRITE8_HANDLER ( pcjr_fdc_w );
+#endif
#endif /* PC_FDC_H */
diff --git a/src/mess/machine/pf10.c b/src/mess/machine/pf10.c
index 532b22bb444..592466b7ad1 100644
--- a/src/mess/machine/pf10.c
+++ b/src/mess/machine/pf10.c
@@ -57,21 +57,12 @@ ADDRESS_MAP_END
MACHINE CONFIG
*****************************************************************************/
-static const upd765_interface pf10_upd765a_intf =
-{
- DEVCB_NULL, /* interrupt line */
- DEVCB_NULL,
- NULL,
- UPD765_RDY_PIN_NOT_CONNECTED, /* ??? */
- {NULL, NULL, NULL, NULL}
-};
-
static MACHINE_CONFIG_FRAGMENT( pf10 )
MCFG_CPU_ADD("pf10", M6803, XTAL_2_4576MHz / 4 /* ??? */) /* HD63A03 */
MCFG_CPU_PROGRAM_MAP(pf10_mem)
MCFG_CPU_IO_MAP(pf10_io)
- MCFG_UPD765A_ADD("upd765a", pf10_upd765a_intf)
+ MCFG_UPD765A_ADD("upd765a", false, true)
MACHINE_CONFIG_END
diff --git a/src/mess/machine/tf20.c b/src/mess/machine/tf20.c
index bec671478f1..e01cddfa489 100644
--- a/src/mess/machine/tf20.c
+++ b/src/mess/machine/tf20.c
@@ -16,7 +16,7 @@
#include "machine/upd7201.h"
#include "machine/upd765.h"
#include "imagedev/flopdrv.h"
-
+#include "formats/mfi_dsk.h"
/***************************************************************************
CONSTANTS
@@ -32,11 +32,16 @@
struct tf20_state
{
+ device_t *cpu;
ram_device *ram;
- device_t *upd765a;
+ upd765a_device *upd765a;
upd7201_device *upd7201;
- device_t *floppy_0;
- device_t *floppy_1;
+ floppy_image_device *floppy_0;
+ floppy_image_device *floppy_1;
+
+ void fdc_int(bool state) {
+ cpu->execute().set_input_line(INPUT_LINE_IRQ0, state ? ASSERT_LINE : CLEAR_LINE);
+ }
};
@@ -89,15 +94,16 @@ static READ8_HANDLER( tf20_dip_r )
static TIMER_CALLBACK( tf20_upd765_tc_reset )
{
- upd765_tc_w((device_t *)ptr, CLEAR_LINE);
+ static_cast<upd765a_device *>(ptr)->tc_w(false);
}
static READ8_DEVICE_HANDLER( tf20_upd765_tc_r )
{
- logerror("%s: tf20_upd765_tc_r\n", space.machine().describe_context());
+ tf20_state *tf20 = get_safe_token(device->owner());
+ logerror("%s: tf20_upd765_tc_r\n", device->machine().describe_context());
/* toggle tc on read */
- upd765_tc_w(device, ASSERT_LINE);
+ tf20->upd765a->tc_w(true);
space.machine().scheduler().timer_set(attotime::zero, FUNC(tf20_upd765_tc_reset), 0, device);
return 0xff;
@@ -109,8 +115,8 @@ static WRITE8_HANDLER( tf20_fdc_control_w )
logerror("%s: tf20_fdc_control_w %02x\n", space.machine().describe_context(), data);
/* bit 0, motor on signal */
- floppy_mon_w(tf20->floppy_0, !BIT(data, 0));
- floppy_mon_w(tf20->floppy_1, !BIT(data, 0));
+ tf20->floppy_0->mon_w(!BIT(data, 0));
+ tf20->floppy_1->mon_w(!BIT(data, 0));
}
static IRQ_CALLBACK( tf20_irq_ack )
@@ -210,8 +216,7 @@ static ADDRESS_MAP_START( tf20_io, AS_IO, 8, tf20_device )
AM_RANGE(0xf6, 0xf6) AM_READ_LEGACY(tf20_rom_disable)
AM_RANGE(0xf7, 0xf7) AM_READ_LEGACY(tf20_dip_r)
AM_RANGE(0xf8, 0xf8) AM_DEVREAD_LEGACY("5a", tf20_upd765_tc_r) AM_WRITE_LEGACY(tf20_fdc_control_w)
- AM_RANGE(0xfa, 0xfa) AM_DEVREAD_LEGACY("5a", upd765_status_r)
- AM_RANGE(0xfb, 0xfb) AM_DEVREADWRITE_LEGACY("5a", upd765_data_r, upd765_data_w)
+ AM_RANGE(0xfa, 0xfb) AM_DEVICE("5a", upd765a_device, map)
ADDRESS_MAP_END
@@ -266,28 +271,15 @@ static UPD7201_INTERFACE( tf20_upd7201_intf )
}
};
-static const upd765_interface tf20_upd765a_intf =
-{
- DEVCB_CPU_INPUT_LINE("tf20", INPUT_LINE_IRQ0),
- DEVCB_NULL,
- NULL,
- UPD765_RDY_PIN_NOT_CONNECTED,
- {FLOPPY_0, FLOPPY_1, NULL, NULL}
-};
-
-static const floppy_interface tf20_floppy_interface =
-{
- DEVCB_NULL,
- DEVCB_NULL,
- DEVCB_NULL,
- DEVCB_NULL,
- DEVCB_NULL,
- FLOPPY_STANDARD_5_25_DSDD_40,
- LEGACY_FLOPPY_OPTIONS_NAME(default),
- NULL,
+static const floppy_format_type tf20_floppy_formats[] = {
+ FLOPPY_MFI_FORMAT,
NULL
};
+static SLOT_INTERFACE_START( tf20_floppies )
+ SLOT_INTERFACE( "525dd", FLOPPY_525_DD )
+SLOT_INTERFACE_END
+
static MACHINE_CONFIG_FRAGMENT( tf20 )
MCFG_CPU_ADD("tf20", Z80, XTAL_CR1 / 2) /* uPD780C */
MCFG_CPU_PROGRAM_MAP(tf20_mem)
@@ -298,14 +290,15 @@ static MACHINE_CONFIG_FRAGMENT( tf20 )
MCFG_RAM_DEFAULT_SIZE("64k")
/* upd765a floppy controller */
- MCFG_UPD765A_ADD("5a", tf20_upd765a_intf)
+ MCFG_UPD765A_ADD("5a", false, true)
/* upd7201 serial interface */
MCFG_UPD7201_ADD("3a", XTAL_CR1 / 2, tf20_upd7201_intf)
MCFG_TIMER_ADD_PERIODIC("serial_timer", serial_clock, attotime::from_hz(XTAL_CR2 / 128))
/* 2 floppy drives */
- MCFG_LEGACY_FLOPPY_2_DRIVES_ADD(tf20_floppy_interface)
+ MCFG_FLOPPY_DRIVE_ADD("5a:0", tf20_floppies, "525dd", 0, tf20_floppy_formats)
+ MCFG_FLOPPY_DRIVE_ADD("5a:1", tf20_floppies, "525dd", 0, tf20_floppy_formats)
MACHINE_CONFIG_END
@@ -326,10 +319,10 @@ ROM_END
static DEVICE_START( tf20 )
{
tf20_state *tf20 = get_safe_token(device);
- device_t *cpu = device->subdevice("tf20");
- address_space &prg = cpu->memory().space(AS_PROGRAM);
+ tf20->cpu = device->subdevice("tf20");
+ address_space &prg = tf20->cpu->memory().space(AS_PROGRAM);
- cpu->execute().set_irq_acknowledge_callback(tf20_irq_ack);
+ tf20->cpu->execute().set_irq_acknowledge_callback(tf20_irq_ack);
/* ram device */
tf20->ram = device->subdevice<ram_device>("ram");
@@ -339,10 +332,13 @@ static DEVICE_START( tf20 )
throw device_missing_dependencies();
/* locate child devices */
- tf20->upd765a = device->subdevice("5a");
+ tf20->upd765a = device->subdevice<upd765a_device>("5a");
tf20->upd7201 = downcast<upd7201_device *>(device->subdevice("3a"));
- tf20->floppy_0 = device->subdevice(FLOPPY_0);
- tf20->floppy_1 = device->subdevice(FLOPPY_1);
+ tf20->floppy_0 = device->subdevice<floppy_connector>("5a:0")->get_device();
+ tf20->floppy_1 = device->subdevice<floppy_connector>("5a:1")->get_device();
+
+ /* hookup the irq */
+ tf20->upd765a->setup_intrq_cb(upd765a_device::line_cb(FUNC(tf20_state::fdc_int), tf20));
/* enable second half of ram */
prg.install_ram(0x8000, 0xffff, tf20->ram->pointer() + 0x8000);
diff --git a/src/mess/machine/upd765.c b/src/mess/machine/upd765.c
index bb44c341107..29d476b329f 100644
--- a/src/mess/machine/upd765.c
+++ b/src/mess/machine/upd765.c
@@ -1,2570 +1,2139 @@
-/***************************************************************************
+#include "debugger.h"
- machine/upd765.c
+#include "upd765.h"
- Functions to emulate a UPD765/Intel 8272 compatible floppy disk controller
-
- Code by Kevin Thacker.
-
- TODO:
-
- - overrun condition
- - Scan Commands
- - crc error in id field and crc error in data field errors
- - disc not present, and no sectors on track for data, deleted data, write, write deleted,
- read a track etc
- - end of cylinder condition - almost working, needs fixing with
- PCW and PC drivers
- - resolve "ready" state stuff (ready state when reset for PC, ready state change while processing command AND
- while idle)
-
- Changes:
- 091006 (Mariusz Wojcieszek, changes needed by QX-10):
- - allowed "Sense Interrupt Status" command when Seek is active
- - DIO bit in status register (0x40) is cleared when "Read Data" command is executed,
- it is later set during result phase.
-
-***************************************************************************/
-
-#include "emu.h"
-#include "machine/upd765.h"
-
-
-enum UPD765_PHASE
-{
- UPD765_COMMAND_PHASE_FIRST_BYTE,
- UPD765_COMMAND_PHASE_BYTES,
- UPD765_RESULT_PHASE,
- UPD765_EXECUTION_PHASE_READ,
- UPD765_EXECUTION_PHASE_WRITE
-};
-
-/* supported versions */
-enum UPD765_VERSION
-{
- TYPE_UPD765A = 0,
- TYPE_UPD765B = 1,
- TYPE_SMC37C78 = 2,
- TYPE_UPD72065 = 3
-};
-
-
-/* uncomment the following line for verbose information */
-#define LOG_VERBOSE 0
-#define LOG_COMMAND 0
-#define LOG_EXTRA 0
-#define LOG_INTERRUPT 0
-
-/* uncomment this to not allow end of cylinder "error" */
-#define NO_END_OF_CYLINDER
+const device_type UPD765A = &device_creator<upd765a_device>;
+const device_type UPD765B = &device_creator<upd765b_device>;
+const device_type I8272A = &device_creator<i8272a_device>;
+const device_type UPD72065 = &device_creator<upd72065_device>;
+const device_type SMC37C78 = &device_creator<smc37c78_device>;
+const device_type N82077AA = &device_creator<n82077aa_device>;
+const device_type PC_FDC_SUPERIO = &device_creator<pc_fdc_superio_device>;
+DEVICE_ADDRESS_MAP_START(map, 8, upd765a_device)
+ AM_RANGE(0x0, 0x0) AM_READ(msr_r)
+ AM_RANGE(0x1, 0x1) AM_READWRITE(fifo_r, fifo_w)
+ADDRESS_MAP_END
+DEVICE_ADDRESS_MAP_START(map, 8, upd765b_device)
+ AM_RANGE(0x0, 0x0) AM_READ(msr_r)
+ AM_RANGE(0x1, 0x1) AM_READWRITE(fifo_r, fifo_w)
+ADDRESS_MAP_END
-/* state of upd765 Interrupt (INT) output */
-#define UPD765_INT 0x02
-/* data rate for floppy discs (MFM data) */
-#define UPD765_DATA_RATE 32
-/* state of upd765 terminal count input*/
-#define UPD765_TC 0x04
+DEVICE_ADDRESS_MAP_START(map, 8, i8272a_device)
+ AM_RANGE(0x0, 0x0) AM_READ(msr_r)
+ AM_RANGE(0x1, 0x1) AM_READWRITE(fifo_r, fifo_w)
+ADDRESS_MAP_END
-#define UPD765_DMA_MODE 0x08
+DEVICE_ADDRESS_MAP_START(map, 8, upd72065_device)
+ AM_RANGE(0x0, 0x0) AM_READ(msr_r)
+ AM_RANGE(0x1, 0x1) AM_READWRITE(fifo_r, fifo_w)
+ADDRESS_MAP_END
-#define UPD765_SEEK_OPERATION_IS_RECALIBRATE 0x01
+DEVICE_ADDRESS_MAP_START(map, 8, smc37c78_device)
+ AM_RANGE(0x2, 0x2) AM_READWRITE(dor_r, dor_w)
+ AM_RANGE(0x3, 0x3) AM_READWRITE(tdr_r, tdr_w)
+ AM_RANGE(0x4, 0x4) AM_READWRITE(msr_r, dsr_w)
+ AM_RANGE(0x5, 0x5) AM_READWRITE(fifo_r, fifo_w)
+ AM_RANGE(0x7, 0x7) AM_READWRITE(dir_r, ccr_w)
+ADDRESS_MAP_END
-#define UPD765_SEEK_ACTIVE 0x010
-/* state of upd765 DMA DRQ output */
-#define UPD765_DMA_DRQ 0x020
-/* state of upd765 FDD READY input */
-#define UPD765_FDD_READY 0x040
+DEVICE_ADDRESS_MAP_START(map, 8, n82077aa_device)
+ AM_RANGE(0x0, 0x0) AM_READ(sra_r)
+ AM_RANGE(0x1, 0x1) AM_READ(srb_r)
+ AM_RANGE(0x2, 0x2) AM_READWRITE(dor_r, dor_w)
+ AM_RANGE(0x3, 0x3) AM_READWRITE(tdr_r, tdr_w)
+ AM_RANGE(0x4, 0x4) AM_READWRITE(msr_r, dsr_w)
+ AM_RANGE(0x5, 0x5) AM_READWRITE(fifo_r, fifo_w)
+ AM_RANGE(0x7, 0x7) AM_READWRITE(dir_r, ccr_w)
+ADDRESS_MAP_END
-#define UPD765_MF 0x40
-#define UPD765_MT 0x80
+DEVICE_ADDRESS_MAP_START(map, 8, pc_fdc_superio_device)
+ AM_RANGE(0x0, 0x0) AM_READ(sra_r)
+ AM_RANGE(0x1, 0x1) AM_READ(srb_r)
+ AM_RANGE(0x2, 0x2) AM_READWRITE(dor_r, dor_w)
+ AM_RANGE(0x3, 0x3) AM_READWRITE(tdr_r, tdr_w)
+ AM_RANGE(0x4, 0x4) AM_READWRITE(msr_r, dsr_w)
+ AM_RANGE(0x5, 0x5) AM_READWRITE(fifo_r, fifo_w)
+ AM_RANGE(0x7, 0x7) AM_READWRITE(dir_r, ccr_w)
+ADDRESS_MAP_END
-#define UPD765_RESET 0x080
-#define UPD765_BAD_MEDIA 0x100
+int upd765_family_device::rates[4] = { 500000, 300000, 250000, 1000000 };
-struct upd765_t
+upd765_family_device::upd765_family_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock) : pc_fdc_interface(mconfig, type, name, tag, owner, clock)
{
- devcb_resolved_write_line out_int_func;
- devcb_resolved_write_line out_drq_func;
-
- unsigned long sector_counter;
- /* version of fdc to emulate */
- UPD765_VERSION version;
-
- /* main status register */
- unsigned char FDC_main;
- /* data register */
- unsigned char upd765_data_reg;
-
- unsigned char c,h,r,n;
-
- int sector_id;
-
- int data_type;
-
- char format_data[4];
-
- UPD765_PHASE upd765_phase;
- unsigned int upd765_command_bytes[16];
- unsigned int upd765_result_bytes[16];
- unsigned int upd765_transfer_bytes_remaining;
- unsigned int upd765_transfer_bytes_count;
- unsigned int upd765_status[4];
- /* present cylinder number per drive */
- unsigned int pcn[4];
-
- /* drive being accessed. drive outputs from fdc */
- unsigned int drive;
- /* side being accessed: side output from fdc */
- unsigned int side;
-
-
- /* step rate time in us */
- unsigned long srt_in_ms;
-
- unsigned int ncn;
-
-// unsigned int upd765_id_index;
- char *execution_phase_data;
- unsigned int upd765_flags;
+ ready_polled = true;
+ ready_connected = true;
+ select_connected = true;
+ external_ready = true;
+ dor_reset = 0x00;
+}
-// unsigned char specify[2];
-// unsigned char perpendicular_mode[1];
+void upd765_family_device::set_ready_line_connected(bool _ready)
+{
+ ready_connected = _ready;
+}
- int command;
+void upd765_family_device::set_select_lines_connected(bool _select)
+{
+ select_connected = _select;
+}
- UINT8 ready_changed;
+void upd765_family_device::set_mode(int _mode)
+{
+ // TODO
+}
- emu_timer *seek_timer;
- emu_timer *timer;
- int timer_type;
+void upd765_family_device::setup_intrq_cb(line_cb cb)
+{
+ intrq_cb = cb;
+}
- emu_timer *command_timer;
+void upd765_family_device::setup_drq_cb(line_cb cb)
+{
+ drq_cb = cb;
+}
- char *data_buffer;
- const upd765_interface *intf;
+void upd765_family_device::device_start()
+{
+ for(int i=0; i != 4; i++) {
+ char name[2];
+ flopi[i].tm = timer_alloc(i);
+ flopi[i].id = i;
+ if(select_connected) {
+ name[0] = '0'+i;
+ name[1] = 0;
+ floppy_connector *con = subdevice<floppy_connector>(name);
+ if(con) {
+ flopi[i].dev = con->get_device();
+ flopi[i].dev->setup_index_pulse_cb(floppy_image_device::index_pulse_cb(FUNC(upd765_family_device::index_callback), this));
+ } else
+ flopi[i].dev = NULL;
+ } else
+ flopi[i].dev = NULL;
+ }
+ cur_rate = 250000;
+ tc = false;
- bool pool;
-};
+ // reset at upper levels may cause a write to tc ending up with
+ // live_sync, which will crash if the live structure isn't
+ // initialized enough
-//static void upd765_setup_data_request(unsigned char Data);
-static void upd765_setup_command(device_t *device);
-static TIMER_CALLBACK(upd765_continue_command);
-static int upd765_sector_count_complete(device_t *device);
-static void upd765_increment_sector(device_t *device);
-static void upd765_update_state(device_t *device);
-static void upd765_set_dma_drq(device_t *device,int state);
-static void upd765_set_int(device_t *device,int state);
+ cur_live.tm = attotime::never;
+ cur_live.state = IDLE;
+ cur_live.next_state = -1;
+ cur_live.fi = NULL;
-static const INT8 upd765_cmd_size[32] =
-{
- 1,1,9,3,2,9,9,2,1,9,2,1,9,6,1,3,
- 1,9,1,1,1,1,9,1,1,9,1,1,1,9,1,1
-};
+ if(ready_polled) {
+ poll_timer = timer_alloc(TIMER_DRIVE_READY_POLLING);
+ poll_timer->adjust(attotime::from_usec(1024), 0, attotime::from_usec(1024));
+ } else
+ poll_timer = NULL;
-INLINE upd765_t *get_safe_token(device_t *device)
-{
- assert(device != NULL);
- assert(device->type() == UPD765A || device->type() == UPD765B ||
- device->type() == SMC37C78 || device->type() == UPD72065);
-
- return (upd765_t *)downcast<upd765a_device *>(device)->token();
+ cur_irq = false;
}
-static device_t *current_image(device_t *device)
+void upd765_family_device::device_reset()
{
- device_t *image = NULL;
- upd765_t *fdc = get_safe_token(device);
-
- if (!fdc->intf->get_image)
- {
- if (fdc->intf->floppy_drive_tags[fdc->drive] != NULL)
- {
- if (device->owner() != NULL)
- image = device->owner()->subdevice(fdc->intf->floppy_drive_tags[fdc->drive]);
- else
- image = device->machine().device(fdc->intf->floppy_drive_tags[fdc->drive]);
- }
+ main_phase = PHASE_CMD;
+ for(int i=0; i<4; i++) {
+ flopi[i].main_state = IDLE;
+ flopi[i].sub_state = IDLE;
+ flopi[i].irq_seek = false;
+ flopi[i].live = false;
+ flopi[i].ready = !ready_polled;
+ flopi[i].irq_polled = false;
}
- else
- {
- image = fdc->intf->get_image(device, fdc->drive);
- }
- return image;
+ data_irq = false;
+ internal_drq = false;
+ fifo_pos = 0;
+ command_pos = 0;
+ result_pos = 0;
+ fifocfg = FIF_DIS;
+ cur_live.fi = 0;
+ drq = false;
+ cur_live.tm = attotime::never;
+ cur_live.state = IDLE;
+ cur_live.next_state = -1;
+ cur_live.fi = NULL;
+ tc_done = false;
+ st0 = st1 = st2 = st3 = 0x00;
+ dor = dor_reset;
+
+ check_irq();
+ if(ready_polled)
+ poll_timer->adjust(attotime::from_usec(1024), 0, attotime::from_usec(1024));
}
-static void upd765_setup_drive_and_side(device_t *device)
+void upd765_family_device::tc_w(bool _tc)
{
- upd765_t *fdc = get_safe_token(device);
- /* drive index upd765 sees */
- fdc->drive = fdc->upd765_command_bytes[1] & 0x03;
- /* side index upd765 sees */
- fdc->side = (fdc->upd765_command_bytes[1]>>2) & 0x01;
+ logerror("%s: tc=%d\n", tag(), _tc);
+ if(tc != _tc && _tc) {
+ live_sync();
+ tc_done = true;
+ tc = _tc;
+ if(cur_live.fi)
+ general_continue(*cur_live.fi);
+ } else
+ tc = _tc;
}
-
-/* setup status register 0 based on data in status register 1 and 2 */
-static void upd765_setup_st0(device_t *device)
+void upd765_family_device::ready_w(bool _ready)
{
- upd765_t *fdc = get_safe_token(device);
- /* clear completition status bits, drive bits and side bits */
- fdc->upd765_status[0] &= ~((1<<7) | (1<<6) | (1<<2) | (1<<1) | (1<<0));
- /* fill in drive */
- fdc->upd765_status[0] |= fdc->drive | (fdc->side<<2);
-
- /* fill in completion status bits based on bits in st0, st1, st2 */
- /* no error bits set */
- if ((fdc->upd765_status[1] | fdc->upd765_status[2])==0)
- {
- return;
- }
-
- fdc->upd765_status[0] |= 0x040;
+ external_ready = _ready;
}
-
-static int upd765_n_to_bytes(int n)
+bool upd765_family_device::get_ready(int fid)
{
- /* 0-> 128 bytes, 1->256 bytes, 2->512 bytes etc */
- /* data_size = ((1<<(N+7)) */
- return 1<<(n+7);
+ if(ready_connected)
+ return flopi[fid].dev ? flopi[fid].dev->ready_r() : false;
+ return external_ready;
}
-static void upd765_set_data_request(device_t *device)
+void upd765_family_device::set_floppy(floppy_image_device *flop)
{
- upd765_t *fdc = get_safe_token(device);
- fdc->FDC_main |= 0x080;
+ for(int fid=0; fid<4; fid++) {
+ if(flopi[fid].dev)
+ flopi[fid].dev->setup_index_pulse_cb(floppy_image_device::index_pulse_cb());
+ flopi[fid].dev = flop;
+ }
+ if(flop)
+ flop->setup_index_pulse_cb(floppy_image_device::index_pulse_cb(FUNC(upd765_family_device::index_callback), this));
+}
+
+READ8_MEMBER(upd765_family_device::sra_r)
+{
+ UINT8 sra = 0;
+ int fid = dor & 3;
+ floppy_info &fi = flopi[fid];
+ if(fi.dir)
+ sra |= 0x01;
+ if(fi.index)
+ sra |= 0x04;
+ if(cur_rate >= 500000)
+ sra |= 0x08;
+ if(fi.dev && fi.dev->trk00_r())
+ sra |= 0x10;
+ if(fi.main_state == SEEK_WAIT_STEP_SIGNAL_TIME)
+ sra |= 0x20;
+ sra |= 0x40;
+ if(cur_irq)
+ sra |= 0x80;
+ if(mode == MODE_M30)
+ sra ^= 0x1f;
+ return sra;
+}
+
+READ8_MEMBER(upd765_family_device::srb_r)
+{
+ return 0;
}
-static void upd765_clear_data_request(device_t *device)
+READ8_MEMBER(upd765_family_device::dor_r)
{
- upd765_t *fdc = get_safe_token(device);
- fdc->FDC_main &= ~0x080;
+ return dor;
}
-static int upd765_get_rdy(device_t *device)
+WRITE8_MEMBER(upd765_family_device::dor_w)
{
- upd765_t *fdc = get_safe_token(device);
+ logerror("%s: dor = %02x\n", tag(), data);
+ UINT8 diff = dor ^ data;
+ dor = data;
+ if(diff & 4) {
+ UINT8 tmp = dor_reset;
+ dor_reset = dor;
+ device_reset();
+ dor_reset = tmp;
+ }
- if (fdc->intf->rdy_pin == UPD765_RDY_PIN_CONNECTED)
- {
- device_t *img = current_image(device);
- if (img!=NULL) {
- return floppy_drive_get_flag_state(img, FLOPPY_DRIVE_READY);
- } else {
- return 0;
- }
+ for(int i=0; i<4; i++) {
+ floppy_info &fi = flopi[i];
+ if(fi.dev)
+ fi.dev->mon_w(!(dor & (0x10 << i)));
}
- else
- return 1;
+ check_irq();
}
-static void upd765_seek_complete(device_t *device)
+READ8_MEMBER(upd765_family_device::tdr_r)
{
- /* tested on Amstrad CPC */
-
- /* if a seek is done without drive connected: */
- /* abnormal termination of command,
- seek complete,
- not ready
- */
-
- /* if a seek is done with drive connected, but disc missing: */
- /* abnormal termination of command,
- seek complete,
- not ready */
-
- /* if a seek is done with drive connected and disc in drive */
- /* seek complete */
-
-
- /* On the PC however, it appears that recalibrates and seeks can be performed without
- a disc in the drive. */
-
- /* Therefore, the above output is dependant on the state of the drive */
-
- /* In the Amstrad CPC, the drive select is provided by the UPD765. A single port is also
- assigned for setting the drive motor state. The motor state controls the motor of the selected
- drive */
-
- /* On the PC the drive can be selected with the DIGITAL OUTPUT REGISTER, and the motor of each
- of the 4 possible drives is also settable using the same register */
-
- /* Assumption for PC: (NOT TESTED - NEEDS VERIFICATION) */
-
- /* If a seek is done without drive connected: */
- /* abnormal termination of command,
- seek complete,
- fault
- */
-
- /* if a seek is done with drive connected, but disc missing: */
- /* seek complete */
-
- /* if a seek is done with drive connected and disc in drive: */
- /* seek complete */
-
- /* On Amstrad CPC:
- If drive not connected, or drive connected but disc not in drive, not ready!
- If drive connected and drive motor on, ready!
- On PC:
- Drive is always ready!
-
- In 37c78 docs, the ready bits of the upd765 are marked as unused.
- This indicates it is always ready!!!!!
- */
-
- device_t *img = current_image(device);
- upd765_t *fdc = get_safe_token(device);
+ return 0;
+}
- fdc->pcn[fdc->drive] = fdc->ncn;
+WRITE8_MEMBER(upd765_family_device::tdr_w)
+{
+}
- fdc->upd765_status[0] = 0x20;
+READ8_MEMBER(upd765_family_device::msr_r)
+{
+ UINT32 msr = 0;
+ switch(main_phase) {
+ case PHASE_CMD:
+ msr |= MSR_RQM;
+ if(command_pos)
+ msr |= MSR_CB;
+ break;
+ case PHASE_EXEC:
+ msr |= MSR_CB;
+ if(spec & SPEC_ND)
+ msr |= MSR_EXM;
+ if(internal_drq)
+ msr |= MSR_RQM;
+ break;
- /* drive ready? */
- if (img != NULL && upd765_get_rdy(device))
- {
- /* recalibrate? */
- if (fdc->upd765_flags & UPD765_SEEK_OPERATION_IS_RECALIBRATE)
- {
- /* not at track 0? */
- if (fdc->pcn[fdc->drive] != 0)
- /* no, track 0 failed after 77 steps */
- fdc->upd765_status[0] |= 0x40 | 0x10;
- }
- }
- else
- {
- /* abnormal termination, not ready */
- fdc->upd765_status[0] |= 0x40 | 0x08;
+ case PHASE_RESULT:
+ msr |= MSR_RQM|MSR_DIO|MSR_CB;
+ break;
}
+ for(int i=0; i<4; i++)
+ if(flopi[i].main_state == RECALIBRATE || flopi[i].main_state == SEEK)
+ msr |= 1<<i;
- /* set drive and side. note: commented out side to avoid problems with the tf20 */
- fdc->upd765_status[0] |= fdc->drive; //| (fdc->side<<2);
-
- upd765_set_int(device,0);
- upd765_set_int(device,1);
-
- fdc->upd765_flags &= ~UPD765_SEEK_ACTIVE;
+ if(data_irq) {
+ data_irq = false;
+ check_irq();
+ }
- upd765_idle(device);
+ return msr;
}
-static TIMER_CALLBACK(upd765_seek_timer_callback)
+WRITE8_MEMBER(upd765_family_device::dsr_w)
{
- device_t *device = (device_t *)ptr;
- upd765_t *fdc = get_safe_token(device);
- /* seek complete */
- upd765_seek_complete(device);
-
- fdc->seek_timer->reset();
+ dsr = data;
+ cur_rate = rates[dsr & 3];
}
-static void upd765_timer_func(device_t *device, int timer_type)
+void upd765_family_device::set_rate(int rate)
{
- upd765_t *fdc = get_safe_token(device);
- /* type 0 = data transfer mode in execution phase */
- if (fdc->timer_type == 0)
- {
- /* set data request */
- upd765_set_data_request(device);
+ cur_rate = rate;
+}
- fdc->timer_type = 4;
+READ8_MEMBER(upd765_family_device::fifo_r)
+{
+ UINT8 r = 0;
+ switch(main_phase) {
+ case PHASE_EXEC:
+ if(internal_drq)
+ return fifo_pop(false);
+ logerror("%s: fifo_r in phase %d\n", tag(), main_phase);
+ break;
- if (!(fdc->upd765_flags & UPD765_DMA_MODE))
- {
- if (fdc->upd765_command_bytes[0] & UPD765_MF)
- {
- /* MFM */
- fdc->timer->reset(attotime::from_usec(13));
- }
- else
- {
- /* FM */
- fdc->timer->reset(attotime::from_usec(27));
- }
- }
- else
- {
- upd765_timer_func(device, fdc->timer_type);
- }
+ case PHASE_RESULT:
+ r = result[0];
+ result_pos--;
+ memmove(result, result+1, result_pos);
+ if(!result_pos)
+ main_phase = PHASE_CMD;
+ break;
+ default:
+ logerror("%s: fifo_r in phase %d\n", tag(), main_phase);
+ break;
}
- else if (fdc->timer_type==2)
- {
- /* result phase begin */
-
- /* generate a int for specific commands */
- switch (fdc->command) {
- case 2: /* read a track */
- case 5: /* write data */
- case 6: /* read data */
- case 9: /* write deleted data */
- case 10: /* read id */
- case 12: /* read deleted data */
- case 13: /* format at track */
- case 17: /* scan equal */
- case 19: /* scan low or equal */
- case 29: /* scan high or equal */
- upd765_set_int(device,1);
- break;
- default:
+ return r;
+}
+
+WRITE8_MEMBER(upd765_family_device::fifo_w)
+{
+ switch(main_phase) {
+ case PHASE_CMD: {
+ command[command_pos++] = data;
+ int cmd = check_command();
+ if(cmd == C_INCOMPLETE)
break;
+ if(cmd == C_INVALID) {
+ logerror("%s: Invalid on %02x\n", tag(), command[0]);
+ exit(1);
+ command_pos = 0;
+ return;
}
-
- upd765_set_data_request(device);
-
- fdc->timer->reset();
+ start_command(cmd);
+ break;
}
- else if (fdc->timer_type == 4)
- {
- /* if in dma mode, a int is not generated per byte. If not in DMA mode
- a int is generated per byte */
- if (fdc->upd765_flags & UPD765_DMA_MODE)
- {
- upd765_set_dma_drq(device,1);
- }
- else
- {
- if (fdc->FDC_main & (1<<7))
- {
- /* set int to indicate data is ready */
- upd765_set_int(device,1);
- }
+ case PHASE_EXEC:
+ if(internal_drq) {
+ fifo_push(data, false);
+ return;
}
+ logerror("%s: fifo_w in phase %d\n", tag(), main_phase);
+ break;
- fdc->timer->reset();
+ default:
+ logerror("%s: fifo_w in phase %d\n", tag(), main_phase);
+ break;
}
}
-static TIMER_CALLBACK(upd765_timer_callback)
+UINT8 upd765_family_device::do_dir_r()
{
- device_t *device = (device_t *)ptr;
- upd765_timer_func(device,param);
+ floppy_info &fi = flopi[dor & 3];
+ if(fi.dev)
+ return fi.dev->dskchg_r() ? 0x00 : 0x80;
+ return 0x00;
}
-/* after (32-27) the DRQ is set, then 27 us later, the int is set.
-I don't know if this is correct, but it is required for the PCW driver.
-In this driver, the first NMI calls the handler function, furthur NMI's are
-effectively disabled by reading the data before the NMI int can be set.
-*/
-
-static void upd765_setup_timed_generic(device_t *device, int timer_type, attotime duration)
+READ8_MEMBER(upd765_family_device::dir_r)
{
- upd765_t *fdc = get_safe_token(device);
-
- fdc->timer_type = timer_type;
-
- if (!(fdc->upd765_flags & UPD765_DMA_MODE))
- {
- fdc->timer->adjust(duration);
- }
- else
- {
- upd765_timer_func(device,fdc->timer_type);
- fdc->timer->reset();
- }
+ return do_dir_r();
}
-/* setup data request */
-static void upd765_setup_timed_data_request(device_t *device, int bytes)
+WRITE8_MEMBER(upd765_family_device::ccr_w)
{
- /* setup timer to trigger in UPD765_DATA_RATE us */
- upd765_setup_timed_generic(device, 0, attotime::from_usec(32-27) /*UPD765_DATA_RATE)*bytes*/);
+ dsr = (dsr & 0xfc) | (data & 3);
+ cur_rate = rates[data & 3];
}
-/* setup result data request */
-static void upd765_setup_timed_result_data_request(device_t *device)
+void upd765_family_device::set_drq(bool state)
{
- upd765_setup_timed_generic(device, 2, attotime::from_usec(UPD765_DATA_RATE*2));
+ if(state != drq) {
+ drq = state;
+ if(!drq_cb.isnull())
+ drq_cb(drq);
+ }
}
-
-/* sets up a timer to issue a seek complete in signed_tracks time */
-static void upd765_setup_timed_int(device_t *device,int signed_tracks)
+bool upd765_family_device::get_drq() const
{
- upd765_t *fdc = get_safe_token(device);
- /* setup timer to signal after seek time is complete */
- fdc->seek_timer->adjust(attotime::from_double(fdc->srt_in_ms*abs(signed_tracks)*0.001));
+ return drq;
}
-static void upd765_seek_setup(device_t *device, int is_recalibrate)
+void upd765_family_device::enable_transfer()
{
- device_t *img;
- int signed_tracks;
- upd765_t *fdc = get_safe_token(device);
-
- fdc->upd765_flags |= UPD765_SEEK_ACTIVE;
-
- if (is_recalibrate)
- {
- /* head cannot be specified with recalibrate */
- fdc->upd765_command_bytes[1] &=~0x04;
- }
-
- upd765_setup_drive_and_side(device);
-
- img = current_image(device);
-
- fdc->FDC_main |= (1<<fdc->drive);
- fdc->FDC_main |= 0x20; // execution phase
- fdc->FDC_main &= ~0x10; // not busy, can send another seek/recalibrate
- // for a different drive, or sense int status
-
- /* recalibrate command? */
- if (is_recalibrate)
- {
- fdc->upd765_flags |= UPD765_SEEK_OPERATION_IS_RECALIBRATE;
-
- fdc->ncn = 0;
-
- /* if drive is already at track 0, or drive is not ready */
- if (img == NULL || floppy_tk00_r(img) == CLEAR_LINE || (!upd765_get_rdy(device)))
- {
- /* seek completed */
-// upd765_seek_complete(device);
- // delay for the time of 1 step, the PCW does not like immediate recalibrates
- upd765_setup_timed_int(device,1);
+ if(spec & SPEC_ND) {
+ // PIO
+ if(!internal_drq) {
+ internal_drq = true;
+ check_irq();
}
- else
- {
- /* is drive present? */
- if (1) //image_slotexists(img)) //fix me
- {
- /* yes - calculate real number of tracks to seek */
-
- int current_track;
-
- /* get current track */
- current_track = floppy_drive_get_current_track(img);
-
- /* get number of tracks to seek */
- signed_tracks = -current_track;
- }
- else
- {
- /* no, seek 77 tracks and then stop */
- /* true for UPD765A, but not for other variants */
- signed_tracks = -77;
- }
-
- /* perform seek - if drive isn't present it will not do anything */
- floppy_drive_seek(img, signed_tracks);
- if (signed_tracks!=0)
- {
- upd765_setup_timed_int(device,signed_tracks);
- }
- else
- {
- upd765_seek_complete(device);
- }
- }
+ } else {
+ // DMA
+ if(!drq)
+ set_drq(true);
}
- else
- {
-
- fdc->upd765_flags &= ~UPD765_SEEK_OPERATION_IS_RECALIBRATE;
-
- fdc->ncn = fdc->upd765_command_bytes[2];
-
- /* get signed tracks */
- signed_tracks = fdc->ncn - fdc->pcn[fdc->drive];
-
- /* perform seek - if drive isn't present it will not do anything */
- floppy_drive_seek(img, signed_tracks);
-
- /* if no tracks to seek, or drive is not ready, seek is complete */
- if (img == NULL || (signed_tracks==0) || (!upd765_get_rdy(device)))
- {
- upd765_seek_complete(device);
- }
- else
- {
- /* seek complete - issue an interrupt */
- upd765_setup_timed_int(device,signed_tracks);
- }
- }
-// upd765_idle(device);
}
-
-
-static void upd765_setup_execution_phase_read(device_t *device, char *ptr, int size)
+void upd765_family_device::disable_transfer()
{
- upd765_t *fdc = get_safe_token(device);
-
-// fdc->FDC_main &= ~0x040; /* FDC->CPU */
- fdc->FDC_main |= 0x040; /* FDC->CPU */
-
- fdc->upd765_transfer_bytes_count = 0;
- fdc->upd765_transfer_bytes_remaining = size;
- fdc->execution_phase_data = ptr;
- fdc->upd765_phase = UPD765_EXECUTION_PHASE_READ;
-
- upd765_setup_timed_data_request(device, 1);
+ if(spec & SPEC_ND) {
+ internal_drq = false;
+ check_irq();
+ } else
+ set_drq(false);
}
-static void upd765_setup_execution_phase_write(device_t *device, char *ptr, int size)
+void upd765_family_device::fifo_push(UINT8 data, bool internal)
{
- upd765_t *fdc = get_safe_token(device);
-
- fdc->FDC_main &= ~0x040; /* FDC->CPU */
-
- fdc->upd765_transfer_bytes_count = 0;
- fdc->upd765_transfer_bytes_remaining = size;
- fdc->execution_phase_data = ptr;
- fdc->upd765_phase = UPD765_EXECUTION_PHASE_WRITE;
-
- /* setup a data request with first byte */
- upd765_setup_timed_data_request(device,1);
+ if(fifo_pos == 16) {
+ if(internal)
+ st1 |= ST1_OR;
+ return;
+ }
+ fifo[fifo_pos++] = data;
+ fifo_expected--;
+
+ int thr = (fifocfg & FIF_THR)+1;
+ if(!fifo_write && (!fifo_expected || fifo_pos >= thr || (fifocfg & FIF_DIS)))
+ enable_transfer();
+ if(fifo_write && (fifo_pos == 16 || !fifo_expected))
+ disable_transfer();
}
-static void upd765_setup_result_phase(device_t *device, int byte_count)
+UINT8 upd765_family_device::fifo_pop(bool internal)
{
- upd765_t *fdc = get_safe_token(device);
-
- fdc->FDC_main |= 0x040; /* FDC->CPU */
- fdc->FDC_main &= ~0x020; /* not execution phase */
-
- fdc->upd765_transfer_bytes_count = 0;
- fdc->upd765_transfer_bytes_remaining = byte_count;
- fdc->upd765_phase = UPD765_RESULT_PHASE;
-
- upd765_setup_timed_result_data_request(device);
+ if(!fifo_pos) {
+ if(internal)
+ st1 |= ST1_OR;
+ return 0;
+ }
+ UINT8 r = fifo[0];
+ fifo_pos--;
+ memmove(fifo, fifo+1, fifo_pos);
+ if(!fifo_write && !fifo_pos)
+ disable_transfer();
+ int thr = fifocfg & 15;
+ if(fifo_write && fifo_expected && (fifo_pos <= thr || (fifocfg & 0x20)))
+ enable_transfer();
+ return r;
}
-void upd765_idle(device_t *device)
+void upd765_family_device::fifo_expect(int size, bool write)
{
- upd765_t *fdc = get_safe_token(device);
-
- fdc->FDC_main &= ~0x040; /* CPU->FDC */
- fdc->FDC_main &= ~0x020; /* not execution phase */
- fdc->FDC_main &= ~0x010; /* not busy */
- fdc->upd765_phase = UPD765_COMMAND_PHASE_FIRST_BYTE;
-
- upd765_set_data_request(device);
+ fifo_expected = size;
+ fifo_write = write;
+ if(fifo_write)
+ enable_transfer();
}
-
-
-/* change flags */
-static void upd765_change_flags(device_t *device,unsigned int flags, unsigned int mask)
+READ8_MEMBER(upd765_family_device::mdma_r)
{
- unsigned int new_flags;
- unsigned int changed_flags;
- upd765_t *fdc = get_safe_token(device);
-
- assert((flags & ~mask) == 0);
-
- /* compute the new flags and which ones have changed */
- new_flags = fdc->upd765_flags & ~mask;
- new_flags |= flags;
- changed_flags = fdc->upd765_flags ^ new_flags;
- fdc->upd765_flags = new_flags;
-
- /* if interrupt changed, call the handler */
- if (changed_flags & UPD765_INT)
- fdc->out_int_func((fdc->upd765_flags & UPD765_INT) ? 1 : 0);
-
- /* if DRQ changed, call the handler */
- if (changed_flags & UPD765_DMA_DRQ)
- fdc->out_drq_func((fdc->upd765_flags & UPD765_DMA_DRQ) ? 1 : 0);
+ return dma_r();
}
-
-
-/* set int output */
-static void upd765_set_int(device_t *device, int state)
+WRITE8_MEMBER(upd765_family_device::mdma_w)
{
- if (LOG_INTERRUPT)
- logerror("upd765_set_int(): state=%d\n", state);
- upd765_change_flags(device, state ? UPD765_INT : 0, UPD765_INT);
+ dma_w(data);
}
-
-
-/* set dma request output */
-static void upd765_set_dma_drq(device_t *device, int state)
+UINT8 upd765_family_device::dma_r()
{
- upd765_change_flags(device, state ? UPD765_DMA_DRQ : 0, UPD765_DMA_DRQ);
+ return fifo_pop(false);
}
-READ_LINE_DEVICE_HANDLER( upd765_int_r )
+void upd765_family_device::dma_w(UINT8 data)
{
- upd765_t *fdc = get_safe_token(device);
-
- return (fdc->upd765_flags & UPD765_INT) ? 1 : 0;
+ fifo_push(data, false);
}
-READ_LINE_DEVICE_HANDLER( upd765_drq_r )
+void upd765_family_device::live_start(floppy_info &fi, int state)
{
- upd765_t *fdc = get_safe_token(device);
+ cur_live.tm = machine().time();
+ cur_live.state = state;
+ cur_live.next_state = -1;
+ cur_live.fi = &fi;
+ cur_live.shift_reg = 0;
+ cur_live.crc = 0xffff;
+ cur_live.bit_counter = 0;
+ cur_live.data_separator_phase = false;
+ cur_live.data_reg = 0;
+ cur_live.previous_type = live_info::PT_NONE;
+ cur_live.data_bit_context = false;
+ cur_live.byte_counter = 0;
+ cur_live.pll.reset(cur_live.tm);
+ cur_live.pll.set_clock(attotime::from_hz(cur_rate*2));
+ checkpoint_live = cur_live;
+ fi.live = true;
- return (fdc->upd765_flags & UPD765_DMA_DRQ) ? 1 : 0;
+ live_run();
}
-
-/* Drive ready */
-
-/*
-
-A drive will report ready if:
-- drive is selected
-- disc is in the drive
-- disk is rotating at a constant speed (normally 300rpm)
-
-On more modern PCs, a ready signal is not provided by the drive.
-This signal is not used in the PC design and was eliminated to save costs
-If you look at the datasheets for the modern UPD765 variants, you will see the Ready
-signal is not mentioned.
-
-On the original UPD765A, ready signal is required, and some commands will fail if the drive
-is not ready.
-
-
-
-
-*/
-
-
-
-
-/* done when ready state of drive changes */
-/* this ignores if command is active, in which case command should terminate immediatly
-with error */
-static void upd765_set_ready_change_callback(device_t *controller, device_t *img, int state)
+void upd765_family_device::checkpoint()
{
- upd765_t *fdc = get_safe_token(controller);
- int drive = floppy_get_drive(img);
-
- if (LOG_EXTRA)
- logerror("upd765: ready state change\n");
-
- /* drive that changed state */
- fdc->upd765_status[0] = 0x0c0 | drive;
-
- /* not ready */
- if (state==0 && fdc->intf->rdy_pin == UPD765_RDY_PIN_CONNECTED )
- fdc->upd765_status[0] |= 8;
-
- /* trigger an int */
- upd765_set_int(controller, 1);
+ if(cur_live.fi)
+ cur_live.pll.commit(cur_live.fi->dev, cur_live.tm);
+ checkpoint_live = cur_live;
}
-
-/* terminal count input */
-WRITE_LINE_DEVICE_HANDLER( upd765_tc_w )
+void upd765_family_device::rollback()
{
- int old_state;
- upd765_t *fdc = get_safe_token(device);
-
- old_state = fdc->upd765_flags;
-
- /* clear drq */
- upd765_set_dma_drq(device, 0);
-
- fdc->upd765_flags &= ~UPD765_TC;
- if (state)
- {
- fdc->upd765_flags |= UPD765_TC;
- }
-
- /* changed state? */
- if (((fdc->upd765_flags^old_state) & UPD765_TC)!=0)
- {
- /* now set? */
- if ((fdc->upd765_flags & UPD765_TC)!=0)
- {
- /* yes */
- if (fdc->timer)
- {
- if (fdc->timer_type==0)
- {
- fdc->timer->reset();
-
-
- }
- }
-
-#ifdef NO_END_OF_CYLINDER
- fdc->command_timer->adjust(attotime::zero);
-#else
- upd765_update_state(device);
-#endif
- }
- }
+ cur_live = checkpoint_live;
}
-READ8_DEVICE_HANDLER( upd765_status_r )
+void upd765_family_device::live_delay(int state)
{
- upd765_t *fdc = get_safe_token(device);
- if (LOG_EXTRA)
- logerror("%s: upd765_status_r: %02x\n", space.machine().describe_context(), fdc->FDC_main);
- return fdc->FDC_main;
+ cur_live.next_state = state;
+ if(cur_live.tm != machine().time())
+ cur_live.fi->tm->adjust(cur_live.tm - machine().time());
+ else
+ live_sync();
}
-
-/* control mark handling code */
-
-/* if SK==1, and we are executing a read data command, and a deleted data mark is found,
-skip it.
-if SK==1, and we are executing a read deleted data command, and a data mark is found,
-skip it. */
-
-static int upd765_read_skip_sector(device_t *device)
+void upd765_family_device::live_sync()
{
- upd765_t *fdc = get_safe_token(device);
- /* skip set? */
- if ((fdc->upd765_command_bytes[0] & (1<<5))!=0)
- {
- /* read data? */
- if (fdc->command == 0x06)
- {
- /* did we just find a sector with deleted data mark? */
- if (fdc->data_type == UPD765_DAM_DELETED_DATA)
- {
- /* skip it */
- return TRUE;
+ if(!cur_live.tm.is_never()) {
+ if(cur_live.tm > machine().time()) {
+ rollback();
+ live_run(machine().time());
+ cur_live.pll.commit(cur_live.fi->dev, cur_live.tm);
+ } else {
+ cur_live.pll.commit(cur_live.fi->dev, cur_live.tm);
+ if(cur_live.next_state != -1) {
+ cur_live.state = cur_live.next_state;
+ cur_live.next_state = -1;
}
- }
- /* deleted data? */
- else
- if (fdc->command == 0x0c)
- {
- /* did we just find a sector with data mark ? */
- if (fdc->data_type == UPD765_DAM_DATA)
- {
- /* skip it */
- return TRUE;
+ if(cur_live.state == IDLE) {
+ cur_live.pll.stop_writing(cur_live.fi->dev, cur_live.tm);
+ cur_live.tm = attotime::never;
+ cur_live.fi->live = false;
+ cur_live.fi = 0;
}
}
+ cur_live.next_state = -1;
+ checkpoint();
}
-
- /* do not skip */
- return FALSE;
}
-/* this is much closer to how the upd765 actually gets sectors */
-/* used by read data, read deleted data, write data, write deleted data */
-/* What the upd765 does:
-
- - get next sector id from disc
- - if sector id matches id specified in command, it will
- search for next data block and read data from it.
-
- - if the index is seen twice while it is searching for a sector, then the sector cannot be found
-*/
-
-static void upd765_get_next_id(device_t *device, chrn_id *id)
+void upd765_family_device::live_abort()
{
- upd765_t *fdc = get_safe_token(device);
- device_t *img = current_image(device);
-
- /* get next id from disc */
- floppy_drive_get_next_id(img, fdc->side,id);
-
- fdc->sector_id = id->data_id;
-
- /* set correct data type */
- fdc->data_type = UPD765_DAM_DATA;
- if (id->flags & ID_FLAG_DELETED_DATA)
- {
- fdc->data_type = UPD765_DAM_DELETED_DATA;
+ if(!cur_live.tm.is_never() && cur_live.tm > machine().time()) {
+ rollback();
+ live_run(machine().time());
}
-}
-
-static int upd765_get_matching_sector(device_t *device)
-{
- upd765_t *fdc = get_safe_token(device);
- device_t *img = current_image(device);
- chrn_id id;
-
- /* number of times we have seen index hole */
- int index_count = 0;
- if (fdc->upd765_flags & UPD765_BAD_MEDIA) {
- fdc->upd765_status[1] |= 1;
- return FALSE;
+ if(cur_live.fi) {
+ cur_live.pll.stop_writing(cur_live.fi->dev, cur_live.tm);
+ cur_live.fi->live = false;
+ cur_live.fi = 0;
}
- /* get sector id's */
- do
- {
- upd765_get_next_id(device, &id);
-
- /* tested on Amstrad CPC - All bytes must match, otherwise
- a NO DATA error is reported */
- if (id.R == fdc->upd765_command_bytes[4])
- {
- if (id.C == fdc->upd765_command_bytes[2])
- {
- if (id.H == fdc->upd765_command_bytes[3])
- {
- if (id.N == fdc->upd765_command_bytes[5])
- {
- /* end of cylinder is set if:
- 1. sector data is read completely (i.e. no other errors occur like
- no data.
- 2. sector being read is same specified by EOT
- 3. terminal count is not received */
- if (fdc->upd765_command_bytes[4]==fdc->upd765_command_bytes[6])
- {
- /* set end of cylinder */
- fdc->upd765_status[1] |= UPD765_ST1_END_OF_CYLINDER;
- }
-
- return TRUE;
- }
- }
- }
- else
- {
- /* the specified sector ID was found, however, the C value specified
- in the read/write command did not match the C value read from the disc */
-
- /* no data - checked on Amstrad CPC */
- fdc->upd765_status[1] |= UPD765_ST1_NO_DATA;
- /* bad C value */
- fdc->upd765_status[2] |= UPD765_ST2_WRONG_CYLINDER;
-
- if (id.C == 0x0ff)
- {
- /* the C value is 0x0ff which indicates a bad track in the IBM soft-sectored
- format */
- fdc->upd765_status[2] |= UPD765_ST2_BAD_CYLINDER;
- }
+ cur_live.tm = attotime::never;
+ cur_live.state = IDLE;
+ cur_live.next_state = -1;
+}
- return FALSE;
- }
- }
+void upd765_family_device::live_run(attotime limit)
+{
+ if(cur_live.state == IDLE || cur_live.next_state != -1)
+ return;
- /* index set? */
- if (floppy_drive_get_flag_state(img, FLOPPY_DRIVE_INDEX))
- {
- index_count++;
+ if(limit == attotime::never) {
+ if(cur_live.fi->dev)
+ limit = cur_live.fi->dev->time_next_index();
+ if(limit == attotime::never) {
+ // Happens when there's no disk or if the fdc is not
+ // connected to a drive, hence no index pulse. Force a
+ // sync from time to time in that case, so that the main
+ // cpu timeout isn't too painful. Avoids looping into
+ // infinity looking for data too.
+
+ limit = machine().time() + attotime::from_msec(1);
+ cur_live.fi->tm->adjust(attotime::from_msec(1));
}
-
}
- while (index_count!=2);
- if (fdc->upd765_command_bytes[4] != fdc->upd765_command_bytes[6])
- {
- /* no data - specified sector ID was not found */
- fdc->upd765_status[1] |= UPD765_ST1_NO_DATA;
- }
+ for(;;) {
- return 0;
-}
-
-static void upd765_read_complete(device_t *device)
-{
- upd765_t *fdc = get_safe_token(device);
-/* causes problems!!! - need to fix */
-#ifdef NO_END_OF_CYLINDER
- /* set end of cylinder */
- fdc->upd765_status[1] &= ~UPD765_ST1_END_OF_CYLINDER;
-#else
- /* completed read command */
+ switch(cur_live.state) {
+ case SEARCH_ADDRESS_MARK_HEADER:
+ if(read_one_bit(limit))
+ return;
+#if 0
+ fprintf(stderr, "%s: shift = %04x data=%02x c=%d\n", tts(cur_live.tm).cstr(), cur_live.shift_reg,
+ (cur_live.shift_reg & 0x4000 ? 0x80 : 0x00) |
+ (cur_live.shift_reg & 0x1000 ? 0x40 : 0x00) |
+ (cur_live.shift_reg & 0x0400 ? 0x20 : 0x00) |
+ (cur_live.shift_reg & 0x0100 ? 0x10 : 0x00) |
+ (cur_live.shift_reg & 0x0040 ? 0x08 : 0x00) |
+ (cur_live.shift_reg & 0x0010 ? 0x04 : 0x00) |
+ (cur_live.shift_reg & 0x0004 ? 0x02 : 0x00) |
+ (cur_live.shift_reg & 0x0001 ? 0x01 : 0x00),
+ cur_live.bit_counter);
+#endif
- /* end of cylinder is set when:
- - a whole sector has been read
- - terminal count input is not set
- - AND the the sector specified by EOT was read
- */
+ if(cur_live.shift_reg == 0x4489) {
+ cur_live.crc = 0x443b;
+ cur_live.data_separator_phase = false;
+ cur_live.bit_counter = 0;
+ cur_live.state = READ_HEADER_BLOCK_HEADER;
+ }
+ break;
- /* if end of cylinder is set, and we did receive a terminal count, then clear it */
- if ((fdc->upd765_flags & UPD765_TC)!=0)
- {
- /* set end of cylinder */
- fdc->upd765_status[1] &= ~UPD765_ST1_END_OF_CYLINDER;
- }
+ case READ_HEADER_BLOCK_HEADER: {
+ if(read_one_bit(limit))
+ return;
+#if 0
+ fprintf(stderr, "%s: shift = %04x data=%02x counter=%d\n", tts(cur_live.tm).cstr(), cur_live.shift_reg,
+ (cur_live.shift_reg & 0x4000 ? 0x80 : 0x00) |
+ (cur_live.shift_reg & 0x1000 ? 0x40 : 0x00) |
+ (cur_live.shift_reg & 0x0400 ? 0x20 : 0x00) |
+ (cur_live.shift_reg & 0x0100 ? 0x10 : 0x00) |
+ (cur_live.shift_reg & 0x0040 ? 0x08 : 0x00) |
+ (cur_live.shift_reg & 0x0010 ? 0x04 : 0x00) |
+ (cur_live.shift_reg & 0x0004 ? 0x02 : 0x00) |
+ (cur_live.shift_reg & 0x0001 ? 0x01 : 0x00),
+ cur_live.bit_counter);
#endif
+ if(cur_live.bit_counter & 15)
+ break;
+
+ int slot = cur_live.bit_counter >> 4;
- upd765_setup_st0(device);
+ if(slot < 3) {
+ if(cur_live.shift_reg != 0x4489)
+ cur_live.state = SEARCH_ADDRESS_MARK_HEADER;
+ break;
+ }
+ if(cur_live.data_reg != 0xfe) {
+ cur_live.state = SEARCH_ADDRESS_MARK_HEADER;
+ break;
+ }
- fdc->upd765_result_bytes[0] = fdc->upd765_status[0];
- fdc->upd765_result_bytes[1] = fdc->upd765_status[1];
- fdc->upd765_result_bytes[2] = fdc->upd765_status[2];
- fdc->upd765_result_bytes[3] = fdc->upd765_command_bytes[2]; /* C */
- fdc->upd765_result_bytes[4] = fdc->upd765_command_bytes[3]; /* H */
- fdc->upd765_result_bytes[5] = fdc->upd765_command_bytes[4]; /* R */
- fdc->upd765_result_bytes[6] = fdc->upd765_command_bytes[5]; /* N */
+ cur_live.bit_counter = 0;
+ cur_live.state = READ_ID_BLOCK;
- upd765_setup_result_phase(device,7);
-}
+ break;
+ }
-static void upd765_read_data(device_t *device)
-{
- upd765_t *fdc = get_safe_token(device);
- device_t *img = current_image(device);
+ case READ_ID_BLOCK: {
+ if(read_one_bit(limit))
+ return;
+ if(cur_live.bit_counter & 15)
+ break;
+ int slot = (cur_live.bit_counter >> 4)-1;
+
+ if(0)
+ fprintf(stderr, "%s: slot=%d data=%02x crc=%04x\n", tts(cur_live.tm).cstr(), slot, cur_live.data_reg, cur_live.crc);
+ cur_live.idbuf[slot] = cur_live.data_reg;
+ if(slot == 5) {
+ live_delay(IDLE);
+ return;
+ }
+ break;
+ }
- if (!upd765_get_rdy(device))
- {
- fdc->upd765_status[0] = 0x0c0 | (1<<4) | fdc->drive | (fdc->side<<2);
- fdc->upd765_status[1] = 0x00;
- fdc->upd765_status[2] = 0x00;
+ case SEARCH_ADDRESS_MARK_DATA:
+ if(read_one_bit(limit))
+ return;
+#if 0
+ fprintf(stderr, "%s: shift = %04x data=%02x c=%d.%x\n", tts(cur_live.tm).cstr(), cur_live.shift_reg,
+ (cur_live.shift_reg & 0x4000 ? 0x80 : 0x00) |
+ (cur_live.shift_reg & 0x1000 ? 0x40 : 0x00) |
+ (cur_live.shift_reg & 0x0400 ? 0x20 : 0x00) |
+ (cur_live.shift_reg & 0x0100 ? 0x10 : 0x00) |
+ (cur_live.shift_reg & 0x0040 ? 0x08 : 0x00) |
+ (cur_live.shift_reg & 0x0010 ? 0x04 : 0x00) |
+ (cur_live.shift_reg & 0x0004 ? 0x02 : 0x00) |
+ (cur_live.shift_reg & 0x0001 ? 0x01 : 0x00),
+ cur_live.bit_counter >> 4, cur_live.bit_counter & 15);
+#endif
+ // Large tolerance due to perpendicular recording at extended density
+ if(cur_live.bit_counter > 62*16) {
+ live_delay(SEARCH_ADDRESS_MARK_DATA_FAILED);
+ return;
+ }
- fdc->upd765_result_bytes[0] = fdc->upd765_status[0];
- fdc->upd765_result_bytes[1] = fdc->upd765_status[1];
- fdc->upd765_result_bytes[2] = fdc->upd765_status[2];
- fdc->upd765_result_bytes[3] = fdc->upd765_command_bytes[2]; /* C */
- fdc->upd765_result_bytes[4] = fdc->upd765_command_bytes[3]; /* H */
- fdc->upd765_result_bytes[5] = fdc->upd765_command_bytes[4]; /* R */
- fdc->upd765_result_bytes[6] = fdc->upd765_command_bytes[5]; /* N */
- upd765_setup_result_phase(device,7);
- return;
- }
+ if(cur_live.bit_counter >= 28*16 && cur_live.shift_reg == 0x4489) {
+ cur_live.crc = 0x443b;
+ cur_live.data_separator_phase = false;
+ cur_live.bit_counter = 0;
+ cur_live.state = READ_DATA_BLOCK_HEADER;
+ }
+ break;
- if (LOG_VERBOSE)
- logerror("sector c: %02x h: %02x r: %02x n: %02x\n",fdc->upd765_command_bytes[2], fdc->upd765_command_bytes[3],fdc->upd765_command_bytes[4], fdc->upd765_command_bytes[5]);
-
- /* find a sector to read data from */
- {
- int found_sector_to_read;
-
- found_sector_to_read = 0;
- /* check for finished reading sectors */
- do
- {
- /* get matching sector */
- if (upd765_get_matching_sector(device))
- {
-
- /* skip it? */
- if (upd765_read_skip_sector(device))
- {
- /* yes */
-
- /* check that we haven't finished reading all sectors */
- if (upd765_sector_count_complete(device))
- {
- /* read complete */
- upd765_read_complete(device);
- return;
- }
+ case READ_DATA_BLOCK_HEADER: {
+ if(read_one_bit(limit))
+ return;
+#if 0
+ fprintf(stderr, "%s: shift = %04x data=%02x counter=%d\n", tts(cur_live.tm).cstr(), cur_live.shift_reg,
+ (cur_live.shift_reg & 0x4000 ? 0x80 : 0x00) |
+ (cur_live.shift_reg & 0x1000 ? 0x40 : 0x00) |
+ (cur_live.shift_reg & 0x0400 ? 0x20 : 0x00) |
+ (cur_live.shift_reg & 0x0100 ? 0x10 : 0x00) |
+ (cur_live.shift_reg & 0x0040 ? 0x08 : 0x00) |
+ (cur_live.shift_reg & 0x0010 ? 0x04 : 0x00) |
+ (cur_live.shift_reg & 0x0004 ? 0x02 : 0x00) |
+ (cur_live.shift_reg & 0x0001 ? 0x01 : 0x00),
+ cur_live.bit_counter);
+#endif
+ if(cur_live.bit_counter & 15)
+ break;
- /* read not finished */
+ int slot = cur_live.bit_counter >> 4;
- /* increment sector count */
- upd765_increment_sector(device);
- }
- else
- {
- /* found a sector to read */
- found_sector_to_read = 1;
+ if(slot < 3) {
+ if(cur_live.shift_reg != 0x4489) {
+ live_delay(SEARCH_ADDRESS_MARK_DATA_FAILED);
+ return;
}
+ break;
}
- else
- {
- /* error in finding sector */
- upd765_read_complete(device);
+ if(cur_live.data_reg != 0xfb && cur_live.data_reg != 0xfd) {
+ live_delay(SEARCH_ADDRESS_MARK_DATA_FAILED);
return;
}
- }
- while (found_sector_to_read==0);
- }
-
- {
- int data_size;
-
- data_size = upd765_n_to_bytes(fdc->upd765_command_bytes[5]);
-
- floppy_drive_read_sector_data(img, fdc->side, fdc->sector_id,fdc->data_buffer,data_size);
-
- upd765_setup_execution_phase_read(device,fdc->data_buffer, data_size);
- }
-}
+ cur_live.bit_counter = 0;
+ cur_live.state = READ_SECTOR_DATA;
+ break;
+ }
-static void upd765_format_track(device_t *device)
-{
- upd765_t *fdc = get_safe_token(device);
- device_t *img = current_image(device);
+ case SEARCH_ADDRESS_MARK_DATA_FAILED:
+ st1 |= ST1_MA;
+ st2 |= ST2_MD;
+ cur_live.state = IDLE;
+ return;
- /* write protected? */
- if (floppy_wpt_r(img) == CLEAR_LINE)
- {
- fdc->upd765_status[1] |= UPD765_ST1_NOT_WRITEABLE;
+ case READ_SECTOR_DATA: {
+ if(read_one_bit(limit))
+ return;
+ if(cur_live.bit_counter & 15)
+ break;
+ int slot = (cur_live.bit_counter >> 4)-1;
+ if(slot < sector_size) {
+ // Sector data
+ live_delay(READ_SECTOR_DATA_BYTE);
+ return;
- upd765_setup_st0(device);
- /* TODO: Check result is correct */
- fdc->upd765_result_bytes[0] = fdc->upd765_status[0];
- fdc->upd765_result_bytes[1] = fdc->upd765_status[1];
- fdc->upd765_result_bytes[2] = fdc->upd765_status[2];
- fdc->upd765_result_bytes[3] = fdc->format_data[0];
- fdc->upd765_result_bytes[4] = fdc->format_data[1];
- fdc->upd765_result_bytes[5] = fdc->format_data[2];
- fdc->upd765_result_bytes[6] = fdc->format_data[3];
- upd765_setup_result_phase(device,7);
+ } else if(slot < sector_size+2) {
+ // CRC
+ if(slot == sector_size+1) {
+ live_delay(IDLE);
+ return;
+ }
+ }
+ break;
+ }
- return;
- }
+ case READ_SECTOR_DATA_BYTE:
+ if(!tc_done)
+ fifo_push(cur_live.data_reg, true);
+ cur_live.state = READ_SECTOR_DATA;
+ checkpoint();
+ break;
- upd765_setup_execution_phase_write(device, &fdc->format_data[0], 4);
-}
+ case WRITE_SECTOR_SKIP_GAP2:
+ cur_live.bit_counter = 0;
+ cur_live.byte_counter = 0;
+ cur_live.state = WRITE_SECTOR_SKIP_GAP2_BYTE;
+ checkpoint();
+ break;
-static void upd765_read_a_track(device_t *device)
-{
- upd765_t *fdc = get_safe_token(device);
- int data_size;
+ case WRITE_SECTOR_SKIP_GAP2_BYTE:
+ if(read_one_bit(limit))
+ return;
+ if(cur_live.bit_counter != 22*16)
+ break;
+ cur_live.bit_counter = 0;
+ cur_live.byte_counter = 0;
+ live_delay(WRITE_SECTOR_DATA);
+ return;
+
+ case WRITE_SECTOR_DATA:
+ if(cur_live.byte_counter < 12)
+ live_write_mfm(0x00);
+ else if(cur_live.byte_counter < 15)
+ live_write_raw(0x4489);
+ else if(cur_live.byte_counter < 16) {
+ cur_live.crc = 0xcdb4;
+ live_write_mfm(command[0] & 0x08 ? 0xf8 : 0xfb);
+ } else if(cur_live.byte_counter < 16+sector_size)
+ live_write_mfm(tc_done && !fifo_pos? 0x00 : fifo_pop(true));
+ else if(cur_live.byte_counter < 16+sector_size+2)
+ live_write_mfm(cur_live.crc >> 8);
+ else if(cur_live.byte_counter < 16+sector_size+2+command[7])
+ live_write_mfm(0x4e);
+ else {
+ cur_live.pll.stop_writing(cur_live.fi->dev, cur_live.tm);
+ cur_live.state = IDLE;
+ return;
+ }
+ cur_live.state = WRITE_SECTOR_DATA_BYTE;
+ cur_live.bit_counter = 16;
+ checkpoint();
+ break;
- /* SKIP not allowed with this command! */
+ case WRITE_TRACK_PRE_SECTORS:
+ if(!cur_live.byte_counter && command[3])
+ fifo_expect(4, true);
+ if(cur_live.byte_counter < 80)
+ live_write_mfm(0x4e);
+ else if(cur_live.byte_counter < 92)
+ live_write_mfm(0x00);
+ else if(cur_live.byte_counter < 95)
+ live_write_raw(0x5224);
+ else if(cur_live.byte_counter < 96)
+ live_write_mfm(0xfc);
+ else if(cur_live.byte_counter < 146)
+ live_write_mfm(0x4e);
+ else {
+ cur_live.state = WRITE_TRACK_SECTOR;
+ cur_live.byte_counter = 0;
+ break;
+ }
+ cur_live.state = WRITE_TRACK_PRE_SECTORS_BYTE;
+ cur_live.bit_counter = 16;
+ checkpoint();
+ break;
- /* get next id */
- chrn_id id;
+ case WRITE_TRACK_SECTOR:
+ if(!cur_live.byte_counter) {
+ command[3]--;
+ if(command[3])
+ fifo_expect(4, true);
+ }
+ if(cur_live.byte_counter < 12)
+ live_write_mfm(0x00);
+ else if(cur_live.byte_counter < 15)
+ live_write_raw(0x4489);
+ else if(cur_live.byte_counter < 16) {
+ cur_live.crc = 0xcdb4;
+ live_write_mfm(0xfe);
+ } else if(cur_live.byte_counter < 20)
+ live_write_mfm(fifo_pop(true));
+ else if(cur_live.byte_counter < 22)
+ live_write_mfm(cur_live.crc >> 8);
+ else if(cur_live.byte_counter < 44)
+ live_write_mfm(0x4e);
+ else if(cur_live.byte_counter < 56)
+ live_write_mfm(0x00);
+ else if(cur_live.byte_counter < 59)
+ live_write_raw(0x4489);
+ else if(cur_live.byte_counter < 60) {
+ cur_live.crc = 0xcdb4;
+ live_write_mfm(0xfb);
+ } else if(cur_live.byte_counter < 60+sector_size)
+ live_write_mfm(command[5]);
+ else if(cur_live.byte_counter < 62+sector_size)
+ live_write_mfm(cur_live.crc >> 8);
+ else if(cur_live.byte_counter < 62+sector_size+command[4])
+ live_write_mfm(0x4e);
+ else {
+ cur_live.byte_counter = 0;
+ cur_live.state = command[3] ? WRITE_TRACK_SECTOR : WRITE_TRACK_POST_SECTORS;
+ break;
+ }
+ cur_live.state = WRITE_TRACK_SECTOR_BYTE;
+ cur_live.bit_counter = 16;
+ checkpoint();
+ break;
- upd765_get_next_id(device, &id);
+ case WRITE_TRACK_POST_SECTORS:
+ live_write_mfm(0x4e);
+ cur_live.state = WRITE_TRACK_POST_SECTORS_BYTE;
+ cur_live.bit_counter = 16;
+ checkpoint();
+ break;
- /* TO BE CONFIRMED! */
- /* check id from disc */
- if (id.C==fdc->upd765_command_bytes[2])
- {
- if (id.H==fdc->upd765_command_bytes[3])
- {
- if (id.R==fdc->upd765_command_bytes[4])
- {
- if (id.N==fdc->upd765_command_bytes[5])
- {
- /* if ID found, then no data is not set */
- /* otherwise no data will remain set */
- fdc->upd765_status[1] &=~UPD765_ST1_NO_DATA;
- }
+ case WRITE_TRACK_PRE_SECTORS_BYTE:
+ case WRITE_TRACK_SECTOR_BYTE:
+ case WRITE_TRACK_POST_SECTORS_BYTE:
+ case WRITE_SECTOR_DATA_BYTE:
+ if(write_one_bit(limit))
+ return;
+ if(cur_live.bit_counter == 0) {
+ cur_live.byte_counter++;
+ live_delay(cur_live.state-1);
+ return;
}
+ break;
+
+ default:
+ logerror("%s: Unknown live state %d\n", tts(cur_live.tm).cstr(), cur_live.state);
+ return;
}
}
-
-
- data_size = upd765_n_to_bytes(id.N);
-
- floppy_drive_read_sector_data(current_image(device), fdc->side, fdc->sector_id,fdc->data_buffer,data_size);
-
- upd765_setup_execution_phase_read(device,fdc->data_buffer, data_size);
}
-static int upd765_just_read_last_sector_on_track(device_t *device)
+int upd765_family_device::check_command()
{
- if (floppy_drive_get_flag_state(current_image(device), FLOPPY_DRIVE_INDEX))
- return 1;
- return 0;
-}
+ // 0.000010 read track
+ // 00000011 specify
+ // 00000100 sense drive status
+ // ..000101 write data
+ // ...00110 read data
+ // 00000111 recalibrate
+ // 00001000 sense interrupt status
+ // ..001001 write deleted data
+ // 0.001010 read id
+ // ...01100 read deleted data
+ // 0.001101 format track
+ // 00001110 dumpreg
+ // 00001111 seek
+ // 00010000 version
+ // ...10001 scan equal
+ // 00010010 perpendicular mode
+ // 00010011 configure
+ // .0010100 lock
+ // ...10110 verify
+ // ...11001 scan low or equal
+ // ...11101 scan high or equal
+ // 1.001111 relative seek
-static void upd765_write_complete(device_t *device)
-{
- upd765_t *fdc = get_safe_token(device);
+ // MSDOS 6.22 format uses 0xcd to format a track, which makes one
+ // think only the bottom 5 bits are decoded.
-/* causes problems!!! - need to fix */
-#ifdef NO_END_OF_CYLINDER
- /* set end of cylinder */
- fdc->upd765_status[1] &= ~UPD765_ST1_END_OF_CYLINDER;
-#else
- /* completed read command */
+ switch(command[0] & 0x1f) {
+ case 0x02:
+ return command_pos == 9 ? C_READ_TRACK : C_INCOMPLETE;
- /* end of cylinder is set when:
- - a whole sector has been read
- - terminal count input is not set
- - AND the the sector specified by EOT was read
- */
+ case 0x03:
+ return command_pos == 3 ? C_SPECIFY : C_INCOMPLETE;
- /* if end of cylinder is set, and we did receive a terminal count, then clear it */
- if ((fdc->upd765_flags & UPD765_TC)!=0)
- {
- /* set end of cylinder */
- fdc->upd765_status[1] &= ~UPD765_ST1_END_OF_CYLINDER;
- }
-#endif
+ case 0x04:
+ return command_pos == 2 ? C_SENSE_DRIVE_STATUS : C_INCOMPLETE;
- upd765_setup_st0(device);
+ case 0x05:
+ case 0x09:
+ return command_pos == 9 ? C_WRITE_DATA : C_INCOMPLETE;
- fdc->upd765_result_bytes[0] = fdc->upd765_status[0];
- fdc->upd765_result_bytes[1] = fdc->upd765_status[1];
- fdc->upd765_result_bytes[2] = fdc->upd765_status[2];
- fdc->upd765_result_bytes[3] = fdc->upd765_command_bytes[2]; /* C */
- fdc->upd765_result_bytes[4] = fdc->upd765_command_bytes[3]; /* H */
- fdc->upd765_result_bytes[5] = fdc->upd765_command_bytes[4]; /* R */
- fdc->upd765_result_bytes[6] = fdc->upd765_command_bytes[5]; /* N */
+ case 0x06:
+ case 0x0c:
+ return command_pos == 9 ? C_READ_DATA : C_INCOMPLETE;
- upd765_setup_result_phase(device,7);
-}
+ case 0x07:
+ return command_pos == 2 ? C_RECALIBRATE : C_INCOMPLETE;
+ case 0x08:
+ return C_SENSE_INTERRUPT_STATUS;
-static void upd765_write_data(device_t *device)
-{
- upd765_t *fdc = get_safe_token(device);
- if (!upd765_get_rdy(device))
- {
- fdc->upd765_status[0] = 0x0c0 | (1<<4) | fdc->drive | (fdc->side<<2);
- fdc->upd765_status[1] = 0x00;
- fdc->upd765_status[2] = 0x00;
-
- fdc->upd765_result_bytes[0] = fdc->upd765_status[0];
- fdc->upd765_result_bytes[1] = fdc->upd765_status[1];
- fdc->upd765_result_bytes[2] = fdc->upd765_status[2];
- fdc->upd765_result_bytes[3] = fdc->upd765_command_bytes[2]; /* C */
- fdc->upd765_result_bytes[4] = fdc->upd765_command_bytes[3]; /* H */
- fdc->upd765_result_bytes[5] = fdc->upd765_command_bytes[4]; /* R */
- fdc->upd765_result_bytes[6] = fdc->upd765_command_bytes[5]; /* N */
- upd765_setup_result_phase(device,7);
- return;
- }
+ case 0x0a:
+ return command_pos == 2 ? C_READ_ID : C_INCOMPLETE;
- /* write protected? */
- if (floppy_wpt_r(current_image(device)) == CLEAR_LINE)
- {
- fdc->upd765_status[1] |= UPD765_ST1_NOT_WRITEABLE;
+ case 0x0d:
+ return command_pos == 6 ? C_FORMAT_TRACK : C_INCOMPLETE;
- upd765_write_complete(device);
- return;
- }
+ case 0x0f:
+ return command_pos == 3 ? C_SEEK : C_INCOMPLETE;
- if (upd765_get_matching_sector(device))
- {
- int data_size;
+ case 0x12:
+ return command_pos == 2 ? C_PERPENDICULAR : C_INCOMPLETE;
- data_size = upd765_n_to_bytes(fdc->upd765_command_bytes[5]);
+ case 0x13:
+ return command_pos == 4 ? C_CONFIGURE : C_INCOMPLETE;
- upd765_setup_execution_phase_write(device,fdc->data_buffer, data_size);
+ default:
+ return C_INVALID;
}
- else
- {
- upd765_setup_result_phase(device,7);
- }
}
+void upd765_family_device::start_command(int cmd)
+{
+ command_pos = 0;
+ result_pos = 0;
+ main_phase = PHASE_EXEC;
+ tc_done = false;
+ switch(cmd) {
+ case C_CONFIGURE:
+ logerror("%s: command configure %02x %02x %02x\n",
+ tag(),
+ command[1], command[2], command[3]);
+ // byte 1 is ignored, byte 3 is precompensation-related
+ fifocfg = command[2];
+ main_phase = PHASE_CMD;
+ break;
-/* return true if we have read all sectors, false if not */
-static int upd765_sector_count_complete(device_t *device)
-{
- upd765_t *fdc = get_safe_token(device);
-/* this is not correct?? */
-#if 1
- /* if terminal count has been set - yes */
- if (fdc->upd765_flags & UPD765_TC)
- {
- /* completed */
- return 1;
- }
+ case C_FORMAT_TRACK:
+ format_track_start(flopi[command[1] & 3]);
+ break;
+ case C_PERPENDICULAR:
+ logerror("%s: command perpendicular\n", tag());
+ main_phase = PHASE_CMD;
+ break;
+ case C_READ_DATA:
+ read_data_start(flopi[command[1] & 3]);
+ break;
- /* multi-track? */
- if (fdc->upd765_command_bytes[0] & UPD765_MT)
- {
- /* it appears that in multi-track mode,
- the EOT parameter of the command is ignored!? -
- or is it ignored the first time and not the next, so that
- if it is started on side 0, it will end at EOT on side 1,
- but if started on side 1 it will end at end of track????
+ case C_READ_ID:
+ read_id_start(flopi[command[1] & 3]);
+ break;
- PC driver requires this to end at last sector on side 1, and
- ignore EOT parameter.
+ case C_READ_TRACK:
+ read_track_start(flopi[command[1] & 3]);
+ break;
- To be checked!!!!
- */
+ case C_RECALIBRATE:
+ recalibrate_start(flopi[command[1] & 3]);
+ main_phase = PHASE_CMD;
+ break;
- /* if just read last sector and on side 1 - finish */
- if (upd765_just_read_last_sector_on_track(device))
- {
- if (floppy_get_heads_per_disk(flopimg_get_image(current_image(device)))==1) {
- return 2;
- } else {
- if (fdc->side==1)
- return 2;
- return 1; // do not advance to next cylinder
- }
- }
+ case C_SEEK:
+ seek_start(flopi[command[1] & 3]);
+ main_phase = PHASE_CMD;
+ break;
- /* if not on second side then we haven't finished yet */
- if (fdc->side!=1)
- {
- /* haven't finished yet */
- return 0;
- }
+ case C_SENSE_DRIVE_STATUS: {
+ floppy_info &fi = flopi[command[1] & 3];
+ main_phase = PHASE_RESULT;
+ result[0] = 0x08;
+ if(get_ready(fi.id))
+ result[0] |= 0x20;
+ if(fi.dev)
+ result[0] |=
+ (fi.dev->wpt_r() ? 0x40 : 0x00) |
+ (fi.dev->trk00_r() ? 0x00 : 0x10) |
+ (fi.dev->ss_r() ? 0x04 : 0x00) |
+ (command[1] & 3);
+ logerror("%s: command sense drive status (%02x)\n", tag(), result[0]);
+ result_pos = 1;
+ break;
}
- else
- {
- /* sector id == EOT? */
- if (fdc->upd765_command_bytes[4]==fdc->upd765_command_bytes[6])
- {
- /* completed */
- return 2;
+ case C_SENSE_INTERRUPT_STATUS: {
+ main_phase = PHASE_RESULT;
+
+ int fid;
+ for(fid=0; fid<4 && !flopi[fid].irq_seek; fid++);
+ if(fid == 4)
+ for(fid=0; fid<4 && !flopi[fid].irq_polled; fid++);
+ if(fid == 4) {
+ st0 = ST0_UNK;
+ result[0] = st0;
+ result[1] = 0x00;
+ result_pos = 2;
+ logerror("%s: command sense interrupt status (%02x %02x)\n", tag(), result[0], result[1]);
+ break;
}
- }
-#else
+ floppy_info &fi = flopi[fid];
+ if(fi.irq_seek)
+ fi.irq_seek = false;
+
+ else if(fi.irq_polled) {
+ // Documentation is somewhat contradictory w.r.t polling
+ // and irq. PC bios, especially 5150, requires that only
+ // one irq happens. That's also wait the ns82077a doc
+ // says it does. OTOH, a number of docs says you need to
+ // call SIS 4 times, once per drive...
+ //
+ // Let's take the option that allows PC to boot.
+
+ for(int i=0; i<4; i++)
+ flopi[i].irq_polled = false;
+
+ st0 = ST0_ABRT | fid;
+ } else {
+ abort();
+ }
+ result[0] = st0;
+ result[1] = fi.pcn;
+ logerror("%s: command sense interrupt status (fid=%d %02x %02x)\n", tag(), fid, result[0], result[1]);
+ result_pos = 2;
- /* if terminal count has been set - yes */
- if (fdc->upd765_flags & UPD765_TC)
- {
- /* completed */
- return 1;
+ check_irq();
+ break;
}
- /* Multi-Track operation:
-
- Verified on Amstrad CPC.
-
- disc format used:
- 9 sectors per track
- 2 sides
- Sector IDs: &01, &02, &03, &04, &05, &06, &07, &08, &09
-
- Command specified:
- SIDE = 0,
- C = 0,H = 0,R = 1, N = 2, EOT = 1
- Sectors read:
- Sector 1 side 0
- Sector 1 side 1
-
- Command specified:
- SIDE = 0,
- C = 0,H = 0,R = 1, N = 2, EOT = 3
- Sectors read:
- Sector 1 side 0
- Sector 2 side 0
- Sector 3 side 0
- Sector 1 side 1
- Sector 2 side 1
- Sector 3 side 1
-
-
- Command specified:
- SIDE = 0,
- C = 0, H = 0, R = 7, N = 2, EOT = 3
- Sectors read:
- Sector 7 side 0
- Sector 8 side 0
- Sector 9 side 0
- Sector 10 not found. Error "No Data"
-
- Command specified:
- SIDE = 1,
- C = 0, H = 1, R = 1, N = 2, EOT = 1
- Sectors read:
- Sector 1 side 1
-
- Command specified:
- SIDE = 1,
- C = 0, H = 1, R = 1, N = 2, EOT = 2
- Sectors read:
- Sector 1 side 1
- Sector 1 side 2
-
- */
-
- /* sector id == EOT? */
- if ((fdc->upd765_command_bytes[4]==fdc->upd765_command_bytes[6]))
- {
- /* multi-track? */
- if (fdc->upd765_command_bytes[0] & 0x080)
- {
- /* if we have reached EOT (fdc->upd765_command_bytes[6])
- on side 1, then read is complete */
- if (fdc->side==1)
- return 1;
-
- return 0;
+ case C_SPECIFY:
+ logerror("%s: command specify %02x %02x\n",
+ tag(),
+ command[1], command[2]);
+ spec = (command[1] << 8) | command[2];
+ main_phase = PHASE_CMD;
+ break;
- }
+ case C_WRITE_DATA:
+ write_data_start(flopi[command[1] & 3]);
+ break;
- /* completed */
- return 1;
+ default:
+ fprintf(stderr, "start command %d\n", cmd);
+ exit(1);
}
-#endif
- /* not complete */
- return 0;
}
-static void upd765_increment_sector(device_t *device)
+void upd765_family_device::command_end(floppy_info &fi, bool data_completion)
{
- upd765_t *fdc = get_safe_token(device);
-
- /* multi-track? */
- if (fdc->upd765_command_bytes[0] & UPD765_MT)
- {
- /* reached EOT? */
- if (fdc->upd765_command_bytes[4] == fdc->upd765_command_bytes[6])
- {
- if (fdc->side == 1)
- {
- fdc->upd765_command_bytes[2]++;
- }
-
- fdc->upd765_command_bytes[3] ^= 0x01;
- fdc->upd765_command_bytes[4] = 1;
- fdc->side = fdc->upd765_command_bytes[3] & 0x01;
- }
- else
- {
- fdc->upd765_command_bytes[4]++;
- }
- }
+ logerror("%s: command done (%s) -", tag(), data_completion ? "data" : "seek");
+ for(int i=0; i != result_pos; i++)
+ logerror(" %02x", result[i]);
+ logerror("\n");
+ fi.main_state = fi.sub_state = IDLE;
+ if(data_completion)
+ data_irq = true;
else
- {
- if (fdc->upd765_command_bytes[4] == fdc->upd765_command_bytes[6])
- {
- fdc->upd765_command_bytes[2]++;
- fdc->upd765_command_bytes[4] = 1;
- }
- else
- {
- fdc->upd765_command_bytes[4]++;
- }
- }
+ fi.irq_seek = true;
+ check_irq();
}
-/* control mark handling code */
-
-/* if SK==0, and we are executing a read data command, and a deleted data sector is found,
-the data is not skipped. The data is read, but the control mark is set and the read is stopped */
-/* if SK==0, and we are executing a read deleted data command, and a data sector is found,
-the data is not skipped. The data is read, but the control mark is set and the read is stopped */
-static int upd765_read_data_stop(device_t *device)
-{
- upd765_t *fdc = get_safe_token(device);
- /* skip not set? */
- if ((fdc->upd765_command_bytes[0] & (1<<5))==0)
- {
- /* read data? */
- if (fdc->command == 0x06)
- {
- /* did we just read a sector with deleted data? */
- if (fdc->data_type == UPD765_DAM_DELETED_DATA)
- {
- /* set control mark */
- fdc->upd765_status[2] |= UPD765_ST2_CONTROL_MARK;
-
- /* quit */
- return TRUE;
- }
- }
- /* deleted data? */
- else
- if (fdc->command == 0x0c)
- {
- /* did we just read a sector with data? */
- if (fdc->data_type == UPD765_DAM_DATA)
- {
- /* set control mark */
- fdc->upd765_status[2] |= UPD765_ST2_CONTROL_MARK;
-
- /* quit */
- return TRUE;
- }
- }
- }
-
- /* continue */
- return FALSE;
+void upd765_family_device::recalibrate_start(floppy_info &fi)
+{
+ logerror("%s: command recalibrate\n", tag());
+ fi.main_state = RECALIBRATE;
+ fi.sub_state = SEEK_WAIT_STEP_TIME_DONE;
+ fi.dir = 1;
+ fi.counter = 77;
+ seek_continue(fi);
}
-static TIMER_CALLBACK(upd765_continue_command)
+void upd765_family_device::seek_start(floppy_info &fi)
{
- device_t *device = (device_t *)ptr;
- upd765_t *fdc = get_safe_token(device);
- if ((fdc->upd765_phase == UPD765_EXECUTION_PHASE_READ) ||
- (fdc->upd765_phase == UPD765_EXECUTION_PHASE_WRITE))
- {
- switch (fdc->command)
- {
- /* read a track */
- case 0x02:
- {
- fdc->sector_counter++;
-
- /* sector counter == EOT */
- if (fdc->sector_counter==fdc->upd765_command_bytes[6])
- {
- /* TODO: Add correct info here */
-
- fdc->upd765_status[1] |= UPD765_ST1_END_OF_CYLINDER;
-
- upd765_setup_st0(device);
-
- fdc->upd765_result_bytes[0] = fdc->upd765_status[0];
- fdc->upd765_result_bytes[1] = fdc->upd765_status[1];
- fdc->upd765_result_bytes[2] = fdc->upd765_status[2];
- fdc->upd765_result_bytes[3] = fdc->upd765_command_bytes[2]; /* C */
- fdc->upd765_result_bytes[4] = fdc->upd765_command_bytes[3]; /* H */
- fdc->upd765_result_bytes[5] = fdc->upd765_command_bytes[4]; /* R */
- fdc->upd765_result_bytes[6] = fdc->upd765_command_bytes[5]; /* N */
+ logerror("%s: command %sseek %d\n", tag(), command[0] & 0x80 ? "relative " : "", command[2]);
+ fi.main_state = SEEK;
+ fi.sub_state = SEEK_WAIT_STEP_TIME_DONE;
+ fi.dir = fi.pcn > command[2] ? 1 : 0;
+ seek_continue(fi);
+}
- upd765_setup_result_phase(device,7);
- }
- else
- {
- upd765_read_a_track(device);
- }
- }
- break;
+void upd765_family_device::delay_cycles(emu_timer *tm, int cycles)
+{
+ tm->adjust(attotime::from_double(double(cycles)/cur_rate));
+}
- /* format track */
- case 0x0d:
- {
- floppy_drive_format_sector(current_image(device), fdc->side, fdc->sector_counter,
- fdc->format_data[0], fdc->format_data[1],
- fdc->format_data[2], fdc->format_data[3],
- fdc->upd765_command_bytes[5]);
-
- fdc->sector_counter++;
-
- /* sector_counter = SC */
- if (fdc->sector_counter == fdc->upd765_command_bytes[3])
- {
- /* TODO: Check result is correct */
- fdc->upd765_result_bytes[0] = fdc->upd765_status[0];
- fdc->upd765_result_bytes[1] = fdc->upd765_status[1];
- fdc->upd765_result_bytes[2] = fdc->upd765_status[2];
- fdc->upd765_result_bytes[3] = fdc->format_data[0];
- fdc->upd765_result_bytes[4] = fdc->format_data[1];
- fdc->upd765_result_bytes[5] = fdc->format_data[2];
- fdc->upd765_result_bytes[6] = fdc->format_data[3];
- upd765_setup_result_phase(device,7);
- }
- else
- {
- upd765_format_track(device);
- }
+void upd765_family_device::seek_continue(floppy_info &fi)
+{
+ for(;;) {
+ switch(fi.sub_state) {
+ case SEEK_MOVE:
+ if(fi.dev) {
+ fi.dev->dir_w(fi.dir);
+ fi.dev->stp_w(0);
}
- break;
+ fi.sub_state = SEEK_WAIT_STEP_SIGNAL_TIME;
+ fi.tm->adjust(attotime::from_nsec(2500));
+ return;
- /* write data, write deleted data */
- case 0x09:
- case 0x05:
- {
- /* sector id == EOT */
- UINT8 ddam;
-
- ddam = 0;
- if (fdc->command == 0x09)
- {
- ddam = 1;
- }
+ case SEEK_WAIT_STEP_SIGNAL_TIME:
+ return;
- /* write data to disc */
- // logerror("floppy_drive_write_sector_data side=%d sector=%d tc=%x\n", fdc->side, fdc->sector_id, fdc->upd765_flags & UPD765_TC);
- floppy_drive_write_sector_data(current_image(device), fdc->side, fdc->sector_id,fdc->data_buffer,upd765_n_to_bytes(fdc->upd765_command_bytes[5]),ddam);
-
- /* nothing to write */
- if ((fdc->upd765_transfer_bytes_remaining==0) && (fdc->upd765_flags & UPD765_DMA_MODE))
- {
- if (fdc->upd765_flags & UPD765_TC)
- {
- upd765_write_complete(device);
- break;
- }
- }
+ case SEEK_WAIT_STEP_SIGNAL_TIME_DONE:
+ if(fi.dev)
+ fi.dev->stp_w(1);
- if (upd765_sector_count_complete(device))
- {
- upd765_increment_sector(device);
- upd765_write_complete(device);
- }
+ if(fi.main_state == SEEK) {
+ if(fi.pcn > command[2])
+ fi.pcn--;
else
- {
- upd765_increment_sector(device);
- upd765_write_data(device);
- }
+ fi.pcn++;
}
- break;
-
- /* read data, read deleted data */
- case 0x0c:
- case 0x06:
- {
-
- int cause;
- /* read all sectors? */
-
- /* sector id == EOT */
- if ((cause = upd765_sector_count_complete(device)) || upd765_read_data_stop(device))
- {
- if (cause == 2)
- upd765_increment_sector(device); // advance to next cylinder if EOT
-
- upd765_read_complete(device);
- }
- else
- {
- upd765_increment_sector(device);
- upd765_read_data(device);
+ fi.sub_state = SEEK_WAIT_STEP_TIME;
+ delay_cycles(fi.tm, 500*(16-(spec >> 12)));
+ return;
+
+ case SEEK_WAIT_STEP_TIME:
+ return;
+
+ case SEEK_WAIT_STEP_TIME_DONE: {
+ bool done = false;
+ switch(fi.main_state) {
+ case RECALIBRATE:
+ fi.counter--;
+ done = !fi.dev || !fi.dev->trk00_r();
+ if(done)
+ fi.pcn = 0;
+ else if(!fi.counter) {
+ st0 = ST0_FAIL|ST0_SE|ST0_EC;
+ command_end(fi, false);
+ return;
}
+ break;
+ case SEEK:
+ done = fi.pcn == command[2];
+ break;
+ }
+ if(done) {
+ st0 = ST0_SE;
+ command_end(fi, false);
+ return;
}
+ fi.sub_state = SEEK_MOVE;
break;
-
- default:
- break;
+ }
}
}
}
-
-static int upd765_get_command_byte_count(device_t *device)
-{
- upd765_t *fdc = get_safe_token(device);
- fdc->command = fdc->upd765_command_bytes[0] & 0x01f;
-
- if (fdc->version==TYPE_UPD765A)
- {
- return upd765_cmd_size[fdc->command];
- }
- else
- {
- if (fdc->version==TYPE_UPD72065)
- {
- switch(fdc->upd765_command_bytes[0])
- {
- case 0x34: // Reset Standby
- case 0x35: // Set Standby
- case 0x36: // Software Reset
- return 1;
- default:
- return upd765_cmd_size[fdc->command];
+void upd765_family_device::read_data_start(floppy_info &fi)
+{
+ fi.main_state = READ_DATA;
+ fi.sub_state = HEAD_LOAD_DONE;
+ logerror("%s: command read%s data%s%s%s%s cmd=%02x sel=%x chrn=(%d, %d, %d, %d) eot=%02x gpl=%02x dtl=%02x rate=%d\n",
+ tag(),
+ command[0] & 0x08 ? " deleted" : "",
+ command[0] & 0x80 ? " mt" : "",
+ command[0] & 0x40 ? " mfm" : "",
+ command[0] & 0x20 ? " sk" : "",
+ fifocfg & 0x40 ? " seek" : "",
+ command[0],
+ command[1],
+ command[2],
+ command[3],
+ command[4],
+ 128 << (command[5] & 7),
+ command[6],
+ command[7],
+ command[8],
+ cur_rate);
+
+ st0 = command[1] & 7;
+ st1 = ST1_MA;
+ st2 = 0x00;
+
+ if(fi.dev)
+ fi.dev->ss_w(command[1] & 4 ? 1 : 0);
+ read_data_continue(fi);
+}
+
+void upd765_family_device::read_data_continue(floppy_info &fi)
+{
+ for(;;) {
+ switch(fi.sub_state) {
+ case HEAD_LOAD_DONE:
+ if(fi.pcn == command[2] || !(fifocfg & 0x40)) {
+ fi.sub_state = SEEK_DONE;
+ break;
}
- }
- if (fdc->version==TYPE_SMC37C78)
- {
- switch (fdc->command)
- {
- /* version */
- case 0x010:
- return 1;
-
- /* verify */
- case 0x016:
- return 9;
-
- /* configure */
- case 0x013:
- return 4;
-
- /* dumpreg */
- case 0x0e:
- return 1;
-
- /* perpendicular mode */
- case 0x012:
- return 1;
-
- /* lock */
- case 0x014:
- return 1;
-
- /* seek/relative seek are together! */
-
- default:
- return upd765_cmd_size[fdc->command];
+ st0 |= ST0_SE;
+ if(fi.dev) {
+ fi.dev->dir_w(fi.pcn > command[2] ? 1 : 0);
+ fi.dev->stp_w(0);
}
- }
- }
-
- return upd765_cmd_size[fdc->command];
-}
+ fi.sub_state = SEEK_WAIT_STEP_SIGNAL_TIME;
+ fi.tm->adjust(attotime::from_nsec(2500));
+ return;
+ case SEEK_WAIT_STEP_SIGNAL_TIME:
+ return;
+ case SEEK_WAIT_STEP_SIGNAL_TIME_DONE:
+ if(fi.dev)
+ fi.dev->stp_w(1);
+ fi.sub_state = SEEK_WAIT_STEP_TIME;
+ delay_cycles(fi.tm, 500*(16-(spec >> 12)));
+ return;
+ case SEEK_WAIT_STEP_TIME:
+ return;
-void upd765_update_state(device_t *device)
-{
- upd765_t *fdc = get_safe_token(device);
- switch (fdc->upd765_phase) {
- case UPD765_RESULT_PHASE:
- /* set data reg */
- fdc->upd765_data_reg = fdc->upd765_result_bytes[fdc->upd765_transfer_bytes_count];
+ case SEEK_WAIT_STEP_TIME_DONE:
+ if(fi.pcn > command[2])
+ fi.pcn--;
+ else
+ fi.pcn++;
+ fi.sub_state = HEAD_LOAD_DONE;
+ break;
- if (fdc->upd765_transfer_bytes_count == 0)
- {
- /* clear int for specific commands */
- switch (fdc->command) {
- case 2: /* read a track */
- case 5: /* write data */
- case 6: /* read data */
- case 9: /* write deleted data */
- case 10: /* read id */
- case 12: /* read deleted data */
- case 13: /* format at track */
- case 17: /* scan equal */
- case 19: /* scan low or equal */
- case 29: /* scan high or equal */
- upd765_set_int(device, 0);
+ case SEEK_DONE:
+ fi.counter = 0;
+ fi.sub_state = SCAN_ID;
+ live_start(fi, SEARCH_ADDRESS_MARK_HEADER);
+ return;
+
+ case SCAN_ID:
+ if(cur_live.crc) {
+ st0 |= ST0_FAIL;
+ st1 |= ST1_DE|ST1_ND;
+ fi.sub_state = COMMAND_DONE;
break;
+ }
+ st1 &= ~ST1_MA;
+ if(!sector_matches()) {
+ if(cur_live.idbuf[0] != command[2]) {
+ if(cur_live.idbuf[0] == 0xff)
+ st2 |= ST2_WC|ST2_BC;
+ else
+ st2 |= ST2_WC;
+ st0 |= ST0_FAIL;
+ fi.sub_state = COMMAND_DONE;
+ break;
+ }
+ live_start(fi, SEARCH_ADDRESS_MARK_HEADER);
+ return;
+ }
+ logerror("%s: reading sector %02x %02x %02x %02x\n",
+ tag(),
+ cur_live.idbuf[0],
+ cur_live.idbuf[1],
+ cur_live.idbuf[2],
+ cur_live.idbuf[3]);
+ sector_size = calc_sector_size(cur_live.idbuf[3]);
+ fifo_expect(sector_size, false);
+ fi.sub_state = SECTOR_READ;
+ live_start(fi, SEARCH_ADDRESS_MARK_DATA);
+ return;
+
+ case SCAN_ID_FAILED:
+ st0 |= ST0_FAIL;
+ st1 |= ST1_ND;
+ fi.sub_state = COMMAND_DONE;
+ break;
- default:
+ case SECTOR_READ: {
+ if(st2 & ST2_MD) {
+ st0 |= ST0_FAIL;
+ fi.sub_state = COMMAND_DONE;
break;
}
+ if(cur_live.crc) {
+ st0 |= ST0_FAIL;
+ st1 |= ST1_DE;
+ st2 |= ST2_CM;
+ fi.sub_state = COMMAND_DONE;
+ break;
+ }
+ bool done = tc_done;
+ command[4]++;
+ if(command[4] > command[6]) {
+ command[4] = 1;
+ if(command[0] & 0x80) {
+ command[3] = command[3] ^ 1;
+ if(fi.dev)
+ fi.dev->ss_w(command[3] & 1);
+ }
+ if(!(command[0] & 0x80) || !(command[3] & 1)) {
+ command[2]++;
+ if(!tc_done) {
+ st0 |= ST0_FAIL;
+ st1 |= ST1_EN;
+ }
+ done = true;
+ }
+ }
+ if(!done) {
+ fi.sub_state = SEEK_DONE;
+ break;
+ }
+ fi.sub_state = COMMAND_DONE;
+ break;
}
- if (LOG_VERBOSE)
- logerror("UPD765: RESULT: %02x\n", fdc->upd765_data_reg);
-
- fdc->upd765_transfer_bytes_count++;
- fdc->upd765_transfer_bytes_remaining--;
-
- if (fdc->upd765_transfer_bytes_remaining==0)
- {
- upd765_idle(device);
- }
- else
- {
- upd765_set_data_request(device);
- }
- break;
-
- case UPD765_EXECUTION_PHASE_READ:
- /* setup data register */
- fdc->upd765_data_reg = fdc->execution_phase_data[fdc->upd765_transfer_bytes_count];
- fdc->upd765_transfer_bytes_count++;
- fdc->upd765_transfer_bytes_remaining--;
-
- if (LOG_EXTRA)
- logerror("EXECUTION PHASE READ: %02x\n", fdc->upd765_data_reg);
-
- if ((fdc->upd765_transfer_bytes_remaining==0) || (fdc->upd765_flags & UPD765_TC))
- {
- fdc->command_timer->adjust(attotime::zero);
- }
- else
- {
- /* trigger int */
- upd765_setup_timed_data_request(device,1);
- }
- break;
-
- case UPD765_COMMAND_PHASE_FIRST_BYTE:
- fdc->FDC_main |= 0x10; /* set BUSY */
-
- if (LOG_VERBOSE)
- logerror("%s: upd765(): command=0x%02x\n", device->machine().describe_context(), fdc->upd765_data_reg);
-
- /* seek in progress? */
- if (fdc->upd765_flags & UPD765_SEEK_ACTIVE)
- {
- /* any command results in a invalid - I think that seek, recalibrate and
- sense interrupt status may work*/
- if (fdc->upd765_data_reg != 8) /* Sense Interrupt Status */
- fdc->upd765_data_reg = 0;
- }
-
- fdc->upd765_command_bytes[0] = fdc->upd765_data_reg;
-
- fdc->upd765_transfer_bytes_remaining = upd765_get_command_byte_count(device);
-
- fdc->upd765_transfer_bytes_count = 1;
- fdc->upd765_transfer_bytes_remaining--;
-
- if (fdc->upd765_transfer_bytes_remaining==0)
- {
- upd765_setup_command(device);
- }
- else
- {
- /* request more data */
- upd765_set_data_request(device);
- fdc->upd765_phase = UPD765_COMMAND_PHASE_BYTES;
- }
- break;
-
- case UPD765_COMMAND_PHASE_BYTES:
- if (LOG_VERBOSE)
- logerror("%s: upd765(): command=0x%02x\n", device->machine().describe_context(), fdc->upd765_data_reg);
-
- fdc->upd765_command_bytes[fdc->upd765_transfer_bytes_count] = fdc->upd765_data_reg;
- fdc->upd765_transfer_bytes_count++;
- fdc->upd765_transfer_bytes_remaining--;
-
- if (fdc->upd765_transfer_bytes_remaining==0)
- {
- upd765_setup_command(device);
- }
- else
- {
- /* request more data */
- upd765_set_data_request(device);
- }
- break;
-
- case UPD765_EXECUTION_PHASE_WRITE:
- fdc->execution_phase_data[fdc->upd765_transfer_bytes_count]=fdc->upd765_data_reg;
- fdc->upd765_transfer_bytes_count++;
- fdc->upd765_transfer_bytes_remaining--;
+ case COMMAND_DONE:
+ main_phase = PHASE_RESULT;
+ result[0] = st0;
+ result[1] = st1;
+ result[2] = st2;
+ result[3] = command[2];
+ result[4] = command[3];
+ result[5] = command[4];
+ result[6] = command[5];
+ result_pos = 7;
+ command_end(fi, true);
+ return;
- if ((fdc->upd765_transfer_bytes_remaining == 0) || (fdc->upd765_flags & UPD765_TC))
- {
- fdc->command_timer->adjust(attotime::zero);
- }
- else
- {
- upd765_setup_timed_data_request(device,1);
+ default:
+ logerror("%s: read sector unknown sub-state %d\n", ttsn().cstr(), fi.sub_state);
+ return;
}
- break;
}
}
+void upd765_family_device::write_data_start(floppy_info &fi)
+{
+ fi.main_state = WRITE_DATA;
+ fi.sub_state = HEAD_LOAD_DONE;
+ logerror("%s: command write%s data%s%s cmd=%02x sel=%x chrn=(%d, %d, %d, %d) eot=%02x gpl=%02x dtl=%02x rate=%d\n",
+ tag(),
+ command[0] & 0x08 ? " deleted" : "",
+ command[0] & 0x80 ? " mt" : "",
+ command[0] & 0x40 ? " mfm" : "",
+ command[0],
+ command[1],
+ command[2],
+ command[3],
+ command[4],
+ 128 << (command[5] & 7),
+ command[6],
+ command[7],
+ command[8],
+ cur_rate);
+
+ if(fi.dev)
+ fi.dev->ss_w(command[1] & 4 ? 1 : 0);
+
+ st0 = command[1] & 7;
+ st1 = ST1_MA;
+ st2 = 0x00;
+
+ write_data_continue(fi);
+}
+
+void upd765_family_device::write_data_continue(floppy_info &fi)
+{
+ for(;;) {
+ switch(fi.sub_state) {
+ case HEAD_LOAD_DONE:
+ fi.counter = 0;
+ fi.sub_state = SCAN_ID;
+ live_start(fi, SEARCH_ADDRESS_MARK_HEADER);
+ return;
+
+ case SCAN_ID:
+ if(!sector_matches()) {
+ live_start(fi, SEARCH_ADDRESS_MARK_HEADER);
+ return;
+ }
+ if(cur_live.crc) {
+ fprintf(stderr, "Header CRC error\n");
+ live_start(fi, SEARCH_ADDRESS_MARK_HEADER);
+ return;
+ }
+ sector_size = calc_sector_size(cur_live.idbuf[3]);
+ fifo_expect(sector_size, true);
+ fi.sub_state = SECTOR_WRITTEN;
+ live_start(fi, WRITE_SECTOR_SKIP_GAP2);
+ return;
+
+ case SCAN_ID_FAILED:
+ st0 |= ST0_FAIL;
+ st1 |= ST1_ND;
+ fi.sub_state = COMMAND_DONE;
+ break;
-READ8_DEVICE_HANDLER(upd765_data_r)
-{
- upd765_t *fdc = get_safe_token(device);
-
-// if ((fdc->FDC_main & 0x0c0) == 0x0c0)
- if ((fdc->FDC_main & 0x080) == 0x080)
- {
- if (
- (fdc->upd765_phase == UPD765_EXECUTION_PHASE_READ) ||
- (fdc->upd765_phase == UPD765_EXECUTION_PHASE_WRITE))
- {
-
- /* reading the data byte clears the interrupt */
- upd765_set_int(device,CLEAR_LINE);
+ case SECTOR_WRITTEN: {
+ bool done = tc_done;
+ command[4]++;
+ if(command[4] > command[6]) {
+ command[4] = 1;
+ if(command[0] & 0x80) {
+ command[3] = command[3] ^ 1;
+ if(fi.dev)
+ fi.dev->ss_w(command[3] & 1);
+ }
+ if(!(command[0] & 0x80) || !(command[3] & 1)) {
+ command[2]++;
+ if(!tc_done) {
+ st0 |= ST0_FAIL;
+ st1 |= ST1_EN;
+ }
+ done = true;
+ }
+ }
+ if(!done) {
+ fi.sub_state = HEAD_LOAD_DONE;
+ break;
+ }
+ fi.sub_state = COMMAND_DONE;
+ break;
}
- /* reset data request */
- upd765_clear_data_request(device);
+ case COMMAND_DONE:
+ main_phase = PHASE_RESULT;
+ result[0] = st0;
+ result[1] = st1;
+ result[2] = st2;
+ result[3] = command[2];
+ result[4] = command[3];
+ result[5] = command[4];
+ result[6] = command[5];
+ result_pos = 7;
+ command_end(fi, true);
+ return;
- /* update state */
- upd765_update_state(device);
+ default:
+ logerror("%s: write sector unknown sub-state %d\n", ttsn().cstr(), fi.sub_state);
+ return;
+ }
}
-
- if (LOG_EXTRA)
- logerror("DATA R: %02x\n", fdc->upd765_data_reg);
-
- return fdc->upd765_data_reg;
}
-WRITE8_DEVICE_HANDLER(upd765_data_w)
+void upd765_family_device::read_track_start(floppy_info &fi)
{
- upd765_t *fdc = get_safe_token(device);
-
- if (LOG_EXTRA)
- logerror("DATA W: %02x\n", data);
+ fi.main_state = READ_TRACK;
+ fi.sub_state = HEAD_LOAD_DONE;
- /* write data to data reg */
- fdc->upd765_data_reg = data;
+ logerror("%s: command read track%s cmd=%02x sel=%x chrn=(%d, %d, %d, %d) eot=%02x gpl=%02x dtl=%02x rate=%d\n",
+ tag(),
+ command[0] & 0x40 ? " mfm" : "",
+ command[0],
+ command[1],
+ command[2],
+ command[3],
+ command[4],
+ 128 << (command[5] & 7),
+ command[6],
+ command[7],
+ command[8],
+ cur_rate);
- if ((fdc->FDC_main & 0x0c0)==0x080)
- {
- if (
- (fdc->upd765_phase == UPD765_EXECUTION_PHASE_READ) ||
- (fdc->upd765_phase == UPD765_EXECUTION_PHASE_WRITE))
- {
-
- /* reading the data byte clears the interrupt */
- upd765_set_int(device, CLEAR_LINE);
- }
-
- /* reset data request */
- upd765_clear_data_request(device);
-
- /* update state */
- upd765_update_state(device);
- }
+ if(fi.dev)
+ fi.dev->ss_w(command[1] & 4 ? 1 : 0);
+ read_track_continue(fi);
}
-static void upd765_setup_invalid(device_t *device)
-{
- upd765_t *fdc = get_safe_token(device);
-
- fdc->command = 0;
- fdc->upd765_result_bytes[0] = 0x080;
- upd765_setup_result_phase(device,1);
-}
-
-static void upd765_setup_command(device_t *device)
-{
- upd765_t *fdc = get_safe_token(device);
-
- static const char *const commands[] =
- {
- NULL, /* [00] */
- NULL, /* [01] */
- "Read Track", /* [02] */
- "Specify", /* [03] */
- "Sense Drive Status", /* [04] */
- "Write Data", /* [05] */
- "Read Data", /* [06] */
- "Recalibrate", /* [07] */
- "Sense Interrupt Status", /* [08] */
- "Write Deleted Data", /* [09] */
- "Read ID", /* [0A] */
- NULL, /* [0B] */
- "Read Deleted Data", /* [0C] */
- "Format Track", /* [0D] */
- "Dump Registers", /* [0E] */
- "Seek", /* [0F] */
- "Version", /* [10] */
- NULL, /* [11] */
- "Perpendicular Mode", /* [12] */
- "Configure", /* [13] */
- "Lock" /* [14] */
- };
-
- device_t *img;
- const char *cmd = NULL;
- chrn_id id;
-
- /* if not in dma mode set execution phase bit */
- if (!(fdc->upd765_flags & UPD765_DMA_MODE))
- {
- fdc->FDC_main |= 0x020; /* execution phase */
- }
-
- if (LOG_COMMAND)
- {
- if ((fdc->upd765_command_bytes[0] & 0x1f) < ARRAY_LENGTH(commands))
- cmd = commands[fdc->upd765_command_bytes[0] & 0x1f];
- logerror("upd765_setup_command(): Setting up command 0x%02X (%s)\n",
- fdc->upd765_command_bytes[0] & 0x1f, cmd ? cmd : "???");
- }
-
- switch (fdc->upd765_command_bytes[0] & 0x1f)
- {
- case 0x03: /* specify */
- /* setup step rate */
- fdc->srt_in_ms = 16-((fdc->upd765_command_bytes[1]>>4) & 0x0f);
-
- fdc->upd765_flags &= ~UPD765_DMA_MODE;
-
- if ((fdc->upd765_command_bytes[2] & 0x01)==0)
- {
- fdc->upd765_flags |= UPD765_DMA_MODE;
+void upd765_family_device::read_track_continue(floppy_info &fi)
+{
+ for(;;) {
+ switch(fi.sub_state) {
+ case HEAD_LOAD_DONE:
+ if(fi.pcn == command[2] || !(fifocfg & 0x40)) {
+ fi.sub_state = SEEK_DONE;
+ break;
}
-
- upd765_idle(device);
- break;
-
- case 0x04: /* sense drive status */
- upd765_setup_drive_and_side(device);
- img = current_image(device);
-
- fdc->upd765_status[3] = fdc->drive | (fdc->side<<2);
-
- if (img)
- {
- fdc->upd765_status[3] |= !floppy_tk00_r(img) << 4;
- fdc->upd765_status[3] |= !floppy_wpt_r(img) << 6;
-
- if (upd765_get_rdy(device))
- {
- fdc->upd765_status[3] |= 0x20;
- }
+ if(fi.dev) {
+ fi.dev->dir_w(fi.pcn > command[2] ? 1 : 0);
+ fi.dev->stp_w(0);
}
+ fi.sub_state = SEEK_WAIT_STEP_SIGNAL_TIME;
+ fi.tm->adjust(attotime::from_nsec(2500));
+ return;
- fdc->upd765_status[3] |= 0x08;
-
- /* two side and fault not set but should be? */
- fdc->upd765_result_bytes[0] = fdc->upd765_status[3];
- upd765_setup_result_phase(device,1);
- break;
-
- case 0x07: /* recalibrate */
- upd765_seek_setup(device, 1);
- break;
-
- case 0x0f: /* seek */
- upd765_seek_setup(device, 0);
- break;
+ case SEEK_WAIT_STEP_SIGNAL_TIME:
+ return;
- case 0x0a: /* read id */
- upd765_setup_drive_and_side(device);
- img = current_image(device);
-
- fdc->upd765_status[0] = fdc->drive | (fdc->side<<2);
- fdc->upd765_status[1] = 0;
- fdc->upd765_status[2] = 0;
-
- /* drive ready? */
- if (upd765_get_rdy(device))
- {
- /* is disk inserted? */
- device_image_interface *image = dynamic_cast<device_image_interface *>( img);
- if (image!=NULL && image->exists())
- {
- int index_count = 0;
-
- /* floppy drive is ready and disc is inserted */
-
- /* this is the id that appears when a disc is not formatted */
- /* to be checked on Amstrad */
- id.C = 0;
- id.H = 0;
- id.R = 0x01;
- id.N = 0x02;
-
- /* repeat for two index counts before quitting */
- do
- {
- /* get next id from disc */
- if (floppy_drive_get_next_id(img, fdc->side, &id))
- {
- /* got an id */
- /* if bad media keep going until failure */
- if (!(fdc->upd765_flags & UPD765_BAD_MEDIA)) break;
- }
-
- if (floppy_drive_get_flag_state(img, FLOPPY_DRIVE_INDEX))
- {
- /* update index count */
- index_count++;
- }
- }
- while (index_count!=2);
+ case SEEK_WAIT_STEP_SIGNAL_TIME_DONE:
+ if(fi.dev)
+ fi.dev->stp_w(1);
- if (fdc->upd765_flags & UPD765_BAD_MEDIA)
- {
- fdc->upd765_status[0] |= 0x40;
- fdc->upd765_status[1] |= 1;
- }
+ fi.sub_state = SEEK_WAIT_STEP_TIME;
+ delay_cycles(fi.tm, 500*(16-(spec >> 12)));
+ return;
- /* at this point, we have seen a id or two index pulses have occurred! */
- fdc->upd765_result_bytes[0] = fdc->upd765_status[0];
- fdc->upd765_result_bytes[1] = fdc->upd765_status[1];
- fdc->upd765_result_bytes[2] = fdc->upd765_status[2];
- fdc->upd765_result_bytes[3] = id.C; /* C */
- fdc->upd765_result_bytes[4] = id.H; /* H */
- fdc->upd765_result_bytes[5] = id.R; /* R */
- fdc->upd765_result_bytes[6] = id.N; /* N */
+ case SEEK_WAIT_STEP_TIME:
+ return;
- upd765_setup_result_phase(device,7);
- }
- else
- {
- /* floppy drive is ready, but no disc is inserted */
- /* this occurs on the PC */
- /* in this case, the command never quits! */
- /* there are no index pulses to stop the command! */
- }
- }
+ case SEEK_WAIT_STEP_TIME_DONE:
+ if(fi.pcn > command[2])
+ fi.pcn--;
else
- {
- /* what are id values when drive not ready? */
-
- /* not ready, abnormal termination */
- fdc->upd765_status[0] |= (1<<3) | (1<<6);
- fdc->upd765_result_bytes[0] = fdc->upd765_status[0];
- fdc->upd765_result_bytes[1] = fdc->upd765_status[1];
- fdc->upd765_result_bytes[2] = fdc->upd765_status[2];
- fdc->upd765_result_bytes[3] = 0; /* C */
- fdc->upd765_result_bytes[4] = 0; /* H */
- fdc->upd765_result_bytes[5] = 0; /* R */
- fdc->upd765_result_bytes[6] = 0; /* N */
- }
+ fi.pcn++;
+ fi.sub_state = HEAD_LOAD_DONE;
break;
+ case SEEK_DONE:
+ fi.counter = 0;
+ fi.sub_state = SCAN_ID;
+ live_start(fi, SEARCH_ADDRESS_MARK_HEADER);
+ return;
- case 0x08: /* sense interrupt status */
- /* interrupt pending? */
- if (fdc->upd765_flags & UPD765_INT)
- {
- /* clear ready changed bit */
- fdc->ready_changed &= ~(1 << fdc->drive);
-
- if (!fdc->pool) {
- fdc->ready_changed = 0;
- }
-
- /* clear drive seek bits */
- fdc->FDC_main &= ~(1 | 2 | 4 | 8);
-
- /* return status */
- fdc->upd765_result_bytes[0] = fdc->upd765_status[0];
- /* return pcn */
- fdc->upd765_result_bytes[1] = fdc->pcn[fdc->drive];
-
- /* return result */
- upd765_setup_result_phase(device,2);
-
- if (fdc->ready_changed)
- {
- fdc->drive++;
- fdc->upd765_status[0] = 0xc0 | fdc->drive;
- }
- else
- {
- /* Clear int */
- upd765_set_int(device, CLEAR_LINE);
- }
+ case SCAN_ID:
+ if(cur_live.crc) {
+ fprintf(stderr, "Header CRC error\n");
+ live_start(fi, SEARCH_ADDRESS_MARK_HEADER);
+ return;
}
- else
- {
- if(fdc->version == TYPE_UPD72065 && (fdc->FDC_main & 0x0f) == 0x00)
- { // based on XM6
- upd765_setup_invalid(device);
- }
- else
- {
- /* no int */
- fdc->upd765_result_bytes[0] = 0x80;
- /* return pcn */
- fdc->upd765_result_bytes[1] = fdc->pcn[fdc->drive];
-
- /* return result */
- upd765_setup_result_phase(device,2);
- }
+ sector_size = calc_sector_size(cur_live.idbuf[3]);
+ fifo_expect(sector_size, false);
+ fi.sub_state = SECTOR_READ;
+ live_start(fi, SEARCH_ADDRESS_MARK_DATA);
+ return;
+
+ case SCAN_ID_FAILED:
+ fprintf(stderr, "RNF\n");
+ // command_end(fi, true, 1);
+ return;
+
+ case SECTOR_READ:
+ if(cur_live.crc) {
+ fprintf(stderr, "CRC error\n");
+ }
+ if(command[4] < command[6]) {
+ command[4]++;
+ fi.sub_state = HEAD_LOAD_DONE;
+ break;
}
- break;
-
- case 0x06: /* read data */
- upd765_setup_drive_and_side(device);
- fdc->upd765_status[0] = fdc->drive | (fdc->side<<2);
- fdc->upd765_status[1] = 0;
- fdc->upd765_status[2] = 0;
+ main_phase = PHASE_RESULT;
+ result[0] = 0x40 | (fi.dev->ss_r() << 2) | fi.id;
+ result[1] = 0;
+ result[2] = 0;
+ result[3] = command[2];
+ result[4] = command[3];
+ result[5] = command[4];
+ result[6] = command[5];
+ result_pos = 7;
+ // command_end(fi, true, 0);
+ return;
- upd765_read_data(device);
- break;
+ default:
+ logerror("%s: read track unknown sub-state %d\n", ttsn().cstr(), fi.sub_state);
+ return;
+ }
+ }
+}
- case 0x0c:
- /* read deleted data */
- upd765_setup_drive_and_side(device);
+int upd765_family_device::calc_sector_size(UINT8 size)
+{
+ return size > 7 ? 16384 : 128 << size;
+}
- fdc->upd765_status[0] = fdc->drive | (fdc->side<<2);
- fdc->upd765_status[1] = 0;
- fdc->upd765_status[2] = 0;
+void upd765_family_device::format_track_start(floppy_info &fi)
+{
+ fi.main_state = FORMAT_TRACK;
+ fi.sub_state = HEAD_LOAD_DONE;
- /* .. for now */
- upd765_read_data(device);
- break;
+ logerror("%s: command format track %s h=%02x n=%02x sc=%02x gpl=%02x d=%02x\n",
+ tag(),
+ command[0] & 0x40 ? "mfm" : "fm",
+ command[1], command[2], command[3], command[4], command[5]);
- case 0x09:
- /* write deleted data */
- upd765_setup_drive_and_side(device);
+ if(fi.dev)
+ fi.dev->ss_w(command[1] & 4 ? 1 : 0);
+ sector_size = calc_sector_size(command[2]);
- fdc->upd765_status[0] = fdc->drive | (fdc->side<<2);
- fdc->upd765_status[1] = 0;
- fdc->upd765_status[2] = 0;
+ format_track_continue(fi);
+}
- /* ... for now */
- upd765_write_data(device);
+void upd765_family_device::format_track_continue(floppy_info &fi)
+{
+ for(;;) {
+ switch(fi.sub_state) {
+ case HEAD_LOAD_DONE:
+ fi.sub_state = WAIT_INDEX;
break;
- case 0x02:
- /* read a track */
- upd765_setup_drive_and_side(device);
- img = current_image(device);
- fdc->upd765_status[0] = fdc->drive | (fdc->side<<2);
- fdc->upd765_status[1] = 0;
- fdc->upd765_status[2] = 0;
-
- fdc->upd765_status[0] |= UPD765_ST1_NO_DATA;
-
- /* wait for index */
- do
- {
- /* get next id from disc */
- floppy_drive_get_next_id(img, fdc->side,&id);
- }
- while ((floppy_drive_get_flag_state(img, FLOPPY_DRIVE_INDEX))==0);
+ case WAIT_INDEX:
+ return;
+
+ case WAIT_INDEX_DONE:
+ logerror("%s: index found, writing track\n", tag());
+ fi.sub_state = TRACK_DONE;
+ cur_live.pll.start_writing(machine().time());
+ live_start(fi, WRITE_TRACK_PRE_SECTORS);
+ return;
+
+ case TRACK_DONE:
+ main_phase = PHASE_RESULT;
+ result[0] = (fi.dev->ss_r() << 2) | fi.id;
+ result[1] = 0;
+ result[2] = 0;
+ result[3] = 0;
+ result[4] = 0;
+ result[5] = 0;
+ result[6] = 0;
+ result_pos = 7;
+ command_end(fi, true);
+ return;
- fdc->sector_counter = 0;
+ default:
+ logerror("%s: format track unknown sub-state %d\n", ttsn().cstr(), fi.sub_state);
+ return;
+ }
+ }
+}
- upd765_read_a_track(device);
- break;
+void upd765_family_device::read_id_start(floppy_info &fi)
+{
+ fi.main_state = READ_ID;
+ fi.sub_state = HEAD_LOAD_DONE;
- case 0x05: /* write data */
- upd765_setup_drive_and_side(device);
+ logerror("%s: command read id%s, rate=%d\n",
+ tag(),
+ command[0] & 0x40 ? " mfm" : "",
+ cur_rate);
- fdc->upd765_status[0] = fdc->drive | (fdc->side<<2);
- fdc->upd765_status[1] = 0;
- fdc->upd765_status[2] = 0;
+ if(fi.dev)
+ fi.dev->ss_w(command[1] & 4 ? 1 : 0);
- upd765_write_data(device);
- break;
+ st0 = command[1] & 7;
+ st1 = 0x00;
+ st2 = 0x00;
- case 0x0d: /* format a track */
- upd765_setup_drive_and_side(device);
+ for(int i=0; i<4; i++)
+ cur_live.idbuf[i] = 0x00;
- fdc->upd765_status[0] = fdc->drive | (fdc->side<<2);
- fdc->upd765_status[1] = 0;
- fdc->upd765_status[2] = 0;
+ read_id_continue(fi);
+}
- fdc->sector_counter = 0;
+void upd765_family_device::read_id_continue(floppy_info &fi)
+{
+ for(;;) {
+ switch(fi.sub_state) {
+ case HEAD_LOAD_DONE:
+ fi.counter = 0;
+ fi.sub_state = SCAN_ID;
+ live_start(fi, SEARCH_ADDRESS_MARK_HEADER);
+ return;
- upd765_format_track(device);
+ case SCAN_ID:
+ if(cur_live.crc) {
+ st0 |= ST0_FAIL;
+ st1 |= ST1_MA|ST1_DE|ST1_ND;
+ }
+ fi.sub_state = COMMAND_DONE;
break;
- default: /* invalid */
- switch (fdc->version)
- {
- case TYPE_UPD765A:
- upd765_setup_invalid(device);
- break;
+ case SCAN_ID_FAILED:
+ st0 |= ST0_FAIL;
+ st1 |= ST1_ND|ST1_MA;
+ fi.sub_state = COMMAND_DONE;
+ break;
- case TYPE_UPD765B:
- /* from upd765b data sheet */
- if ((fdc->upd765_command_bytes[0] & 0x01f)==0x010)
- {
- /* version */
- fdc->upd765_status[0] = 0x090;
- fdc->upd765_result_bytes[0] = fdc->upd765_status[0];
- upd765_setup_result_phase(device,1);
- }
- break;
+ case COMMAND_DONE:
+ main_phase = PHASE_RESULT;
+ result[0] = st0;
+ result[1] = st1;
+ result[2] = st2;
+ result[3] = cur_live.idbuf[0];
+ result[4] = cur_live.idbuf[1];
+ result[5] = cur_live.idbuf[2];
+ result[6] = cur_live.idbuf[3];
+ result_pos = 7;
+ command_end(fi, true);
+ return;
- case TYPE_UPD72065:
- switch(fdc->upd765_command_bytes[0] & 0x3f)
- {
- case 0x36: // Software Reset
- upd765_reset(device,0);
- upd765_idle(device);
- if(LOG_COMMAND)
- logerror("upd72065: command - Software Reset\n");
- break;
- default:
- upd765_setup_invalid(device);
- break;
- }
- break;
-
- case TYPE_SMC37C78:
- /* TO BE COMPLETED!!! !*/
- switch (fdc->upd765_command_bytes[0] & 0x1f)
- {
- case 0x10: /* version */
- fdc->upd765_status[0] = 0x90;
- fdc->upd765_result_bytes[0] = fdc->upd765_status[0];
- upd765_setup_result_phase(device,1);
- break;
-
- case 0x13: /* configure */
- fdc->pool = fdc->upd765_command_bytes[1] & 0x10;
- upd765_idle(device);
- break;
-
- case 0x0e: /* dump reg */
- fdc->upd765_result_bytes[0] = fdc->pcn[0];
- fdc->upd765_result_bytes[1] = fdc->pcn[1];
- fdc->upd765_result_bytes[2] = fdc->pcn[2];
- fdc->upd765_result_bytes[3] = fdc->pcn[3];
-
- upd765_setup_result_phase(device,10);
- break;
-
- case 0x12: /* perpendicular mode */
- upd765_idle(device);
- break;
-
- case 0x14: /* lock */
- upd765_setup_result_phase(device,1);
- break;
- }
- break;
- }
+ default:
+ logerror("%s: read id unknown sub-state %d\n", ttsn().cstr(), fi.sub_state);
+ return;
+ }
}
}
-
-/* dma acknowledge write */
-WRITE8_DEVICE_HANDLER(upd765_dack_w)
+void upd765_family_device::check_irq()
{
- /* clear request */
- upd765_set_dma_drq(device, CLEAR_LINE);
-
- /* write data */
- upd765_data_w(device, space, offset, data);
+ bool old_irq = cur_irq;
+ cur_irq = data_irq || internal_drq;
+ for(int i=0; i<4; i++)
+ cur_irq = cur_irq || flopi[i].irq_seek || flopi[i].irq_polled;
+ cur_irq = cur_irq && (dor & 4) && (dor & 8);
+ if(cur_irq != old_irq && !intrq_cb.isnull()) {
+ logerror("%s: irq = %d\n", tag(), cur_irq);
+ intrq_cb(cur_irq);
+ }
}
-READ8_DEVICE_HANDLER(upd765_dack_r)
+bool upd765_family_device::get_irq() const
{
- /* clear data request */
- upd765_set_dma_drq(device,CLEAR_LINE);
-
- /* read data */
- return upd765_data_r(device, space, offset);
+ return cur_irq;
}
-static TIMER_CALLBACK( interrupt_callback )
+astring upd765_family_device::tts(attotime t)
{
- device_t* device = (device_t*)ptr;
- upd765_set_int(device, 1);
+ char buf[256];
+ const char *sign = "";
+ if(t.seconds < 0) {
+ t = attotime::zero-t;
+ sign = "-";
+ }
+ int nsec = t.attoseconds / ATTOSECONDS_PER_NANOSECOND;
+ sprintf(buf, "%s%04d.%03d,%03d,%03d", sign, int(t.seconds), nsec/1000000, (nsec/1000)%1000, nsec % 1000);
+ return buf;
}
-void upd765_set_bad(device_t *device, int state)
+astring upd765_family_device::ttsn()
{
- upd765_t *fdc = get_safe_token(device);
- if (state) fdc->upd765_flags |= UPD765_BAD_MEDIA;
- else fdc->upd765_flags &= ~UPD765_BAD_MEDIA;
+ return tts(machine().time());
}
-void upd765_reset(device_t *device, int offset)
+void upd765_family_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
- upd765_t *fdc = get_safe_token(device);
+ if(id == TIMER_DRIVE_READY_POLLING) {
+ run_drive_ready_polling();
+ return;
+ }
- /* upd765 in idle state - ready to accept commands */
- upd765_idle(device);
+ live_sync();
+
+ floppy_info &fi = flopi[id];
+ switch(fi.sub_state) {
+ case SEEK_WAIT_STEP_SIGNAL_TIME:
+ fi.sub_state = SEEK_WAIT_STEP_SIGNAL_TIME_DONE;
+ break;
+ case SEEK_WAIT_STEP_TIME:
+ fi.sub_state = SEEK_WAIT_STEP_TIME_DONE;
+ break;
+ }
- /* set int low */
- upd765_set_int(device, 0);
- /* set dma drq output */
- upd765_set_dma_drq(device,0);
+ general_continue(fi);
+}
- /* tandy 100hx assumes that after NEC is reset, it is in DMA mode */
- fdc->upd765_flags |= UPD765_DMA_MODE;
+void upd765_family_device::run_drive_ready_polling()
+{
+ if(main_phase != PHASE_CMD || (fifocfg & FIF_POLL))
+ return;
- /* if ready input is set during reset generate an int */
- if (upd765_get_rdy(device))
- {
- int i;
- int a_drive_is_ready;
+ bool changed = false;
+ for(int fid=0; fid<4; fid++) {
+ bool ready = get_ready(fid);
+ if(ready != flopi[fid].ready) {
+ logerror("%s: polled %d : %d -> %d\n", tag(), fid, flopi[fid].ready, ready);
+ flopi[fid].ready = ready;
+ flopi[fid].irq_polled = true;
+ changed = true;
+ }
+ }
+ if(changed)
+ check_irq();
+}
- fdc->upd765_status[0] = 0x080 | 0x040;
+void upd765_family_device::index_callback(floppy_image_device *floppy, int state)
+{
+ for(int fid=0; fid<4; fid++) {
+ floppy_info &fi = flopi[fid];
+ if(fi.dev != floppy)
+ continue;
- // HACK signal ready changed for all drives
- fdc->ready_changed = 0x0f;
- fdc->drive = 0;
+ if(fi.live)
+ live_sync();
+ fi.index = state;
- /* for the purpose of pc-xt. If any of the drives have a disk inserted,
- do not set not-ready - need to check with pc_fdc.c whether all drives
- are checked or only the drive selected with the drive select bits?? */
+ if(!state) {
+ general_continue(fi);
+ continue;
+ }
- a_drive_is_ready = 0;
- for (i = 0; i < 4; i++)
- {
- if (fdc->intf->floppy_drive_tags[i]!=NULL)
- {
- device_t *img;
+ switch(fi.sub_state) {
+ case IDLE:
+ case SEEK_MOVE:
+ case SEEK_WAIT_STEP_SIGNAL_TIME:
+ case SEEK_WAIT_STEP_SIGNAL_TIME_DONE:
+ case SEEK_WAIT_STEP_TIME:
+ case SEEK_WAIT_STEP_TIME_DONE:
+ case HEAD_LOAD_DONE:
+ case SCAN_ID_FAILED:
+ case SECTOR_READ:
+ break;
- if (device->owner() != NULL)
- img = device->owner()->subdevice(fdc->intf->floppy_drive_tags[i]);
- else
- img = device->machine().device(fdc->intf->floppy_drive_tags[i]);
+ case WAIT_INDEX:
+ fi.sub_state = WAIT_INDEX_DONE;
+ break;
- device_image_interface *image = dynamic_cast<device_image_interface *>( img);
- if (image->exists())
- {
- a_drive_is_ready = 1;
- break;
- }
+ case SCAN_ID:
+ fi.counter++;
+ if(fi.counter == 2) {
+ fi.sub_state = SCAN_ID_FAILED;
+ live_abort();
}
+ break;
- }
+ case TRACK_DONE:
+ live_abort();
+ break;
- if (!a_drive_is_ready && fdc->intf->rdy_pin == UPD765_RDY_PIN_CONNECTED )
- {
- fdc->upd765_status[0] |= 0x08;
+ default:
+ logerror("%s: Index pulse on unknown sub-state %d\n", ttsn().cstr(), fi.sub_state);
+ break;
}
- device->machine().scheduler().timer_set(attotime::from_usec(5), FUNC(interrupt_callback),0,device);
+ general_continue(fi);
}
}
-WRITE_LINE_DEVICE_HANDLER( upd765_reset_w )
+
+void upd765_family_device::general_continue(floppy_info &fi)
{
- upd765_t *fdc = get_safe_token(device);
+ if(fi.live && cur_live.state != IDLE) {
+ live_run();
+ if(cur_live.state != IDLE)
+ return;
+ }
- int flags;
+ switch(fi.main_state) {
+ case IDLE:
+ break;
- /* get previous reset state */
- flags = fdc->upd765_flags;
+ case RECALIBRATE:
+ case SEEK:
+ seek_continue(fi);
+ break;
- /* set new reset state */
- /* clear reset */
- fdc->upd765_flags &= ~UPD765_RESET;
+ case READ_DATA:
+ read_data_continue(fi);
+ break;
- /* reset */
- if (state)
- {
- fdc->upd765_flags |= UPD765_RESET;
+ case WRITE_DATA:
+ write_data_continue(fi);
+ break;
- upd765_set_int(device, 0);
- }
+ case READ_TRACK:
+ read_track_continue(fi);
+ break;
- /* reset changed state? */
- if (((flags^fdc->upd765_flags) & UPD765_RESET)!=0)
- {
- /* yes */
+ case FORMAT_TRACK:
+ format_track_continue(fi);
+ break;
- /* no longer reset */
- if ((fdc->upd765_flags & UPD765_RESET)==0)
- {
- /* reset nec */
- upd765_reset(device, 0);
- }
+ case READ_ID:
+ read_id_continue(fi);
+ break;
+
+ default:
+ logerror("%s: general_continue on unknown main-state %d\n", ttsn().cstr(), fi.main_state);
+ break;
}
}
-
-WRITE_LINE_DEVICE_HANDLER( upd765_ready_w )
+bool upd765_family_device::read_one_bit(attotime limit)
{
- upd765_t *fdc = get_safe_token(device);
-
- /* clear ready state */
- fdc->upd765_flags &= ~UPD765_FDD_READY;
-
- if (state)
- {
- fdc->upd765_flags |= UPD765_FDD_READY;
+ int bit = cur_live.pll.get_next_bit(cur_live.tm, cur_live.fi->dev, limit);
+ if(bit < 0)
+ return true;
+ cur_live.shift_reg = (cur_live.shift_reg << 1) | bit;
+ cur_live.bit_counter++;
+ if(cur_live.data_separator_phase) {
+ cur_live.data_reg = (cur_live.data_reg << 1) | bit;
+ if((cur_live.crc ^ (bit ? 0x8000 : 0x0000)) & 0x8000)
+ cur_live.crc = (cur_live.crc << 1) ^ 0x1021;
+ else
+ cur_live.crc = cur_live.crc << 1;
}
+ cur_live.data_separator_phase = !cur_live.data_separator_phase;
+ return false;
}
-
-/* Device Interface */
-
-static void common_start(device_t *device, int device_type)
+bool upd765_family_device::write_one_bit(attotime limit)
{
- upd765_t *fdc = get_safe_token(device);
- // validate arguments
-
- assert(device != NULL);
- assert(device->tag() != NULL);
- assert(device->static_config() != NULL);
-
- fdc->intf = (const upd765_interface*)device->static_config();
+ bool bit = cur_live.shift_reg & 0x8000;
+ if(cur_live.pll.write_next_bit(bit, cur_live.tm, cur_live.fi->dev, limit))
+ return true;
+ if(cur_live.bit_counter & 1) {
+ if((cur_live.crc ^ (bit ? 0x8000 : 0x0000)) & 0x8000)
+ cur_live.crc = (cur_live.crc << 1) ^ 0x1021;
+ else
+ cur_live.crc = cur_live.crc << 1;
+ }
+ cur_live.shift_reg = cur_live.shift_reg << 1;
+ cur_live.bit_counter--;
+ return false;
+}
- fdc->version = (UPD765_VERSION)device_type;
- fdc->timer = device->machine().scheduler().timer_alloc(FUNC(upd765_timer_callback), (void*)device);
- fdc->seek_timer = device->machine().scheduler().timer_alloc(FUNC(upd765_seek_timer_callback), (void*)device);
- fdc->command_timer = device->machine().scheduler().timer_alloc(FUNC(upd765_continue_command), (void*)device);
+void upd765_family_device::live_write_raw(UINT16 raw)
+{
+ // logerror("write %04x %04x\n", raw, cur_live.crc);
+ cur_live.shift_reg = raw;
+ cur_live.data_bit_context = raw & 1;
+}
- fdc->upd765_flags &= UPD765_FDD_READY;
- fdc->data_buffer = auto_alloc_array(device->machine(), char, 32*1024);
+void upd765_family_device::live_write_mfm(UINT8 mfm)
+{
+ bool context = cur_live.data_bit_context;
+ UINT16 raw = 0;
+ for(int i=0; i<8; i++) {
+ bool bit = mfm & (0x80 >> i);
+ if(!(bit || context))
+ raw |= 0x8000 >> (2*i);
+ if(bit)
+ raw |= 0x4000 >> (2*i);
+ context = bit;
+ }
+ cur_live.data_reg = mfm;
+ cur_live.shift_reg = raw;
+ cur_live.data_bit_context = context;
+ // logerror("write %02x %04x %04x\n", mfm, cur_live.crc, raw);
+}
- fdc->out_int_func.resolve(fdc->intf->out_int_func, *device);
- fdc->out_drq_func.resolve(fdc->intf->out_drq_func, *device);
+bool upd765_family_device::sector_matches() const
+{
+ return
+ cur_live.idbuf[0] == command[2] &&
+ cur_live.idbuf[1] == command[3] &&
+ cur_live.idbuf[2] == command[4] &&
+ cur_live.idbuf[3] == command[5];
+}
- // plain upd765 is doing pooling
- fdc->pool = true;
- // register for state saving
- //state_save_register_item(device->machine(), "upd765", device->tag(), 0, upd765->number);
+void upd765_family_device::pll_t::set_clock(attotime _period)
+{
+ period = _period;
+ period_adjust_base = period * 0.05;
+ min_period = period * 0.75;
+ max_period = period * 1.25;
}
-static DEVICE_START( upd765a )
+void upd765_family_device::pll_t::reset(attotime when)
{
- common_start(device, TYPE_UPD765A);
+ ctime = when;
+ phase_adjust = attotime::zero;
+ freq_hist = 0;
+ write_position = 0;
+ write_start_time = attotime::never;
}
-static DEVICE_START( upd765b )
+void upd765_family_device::pll_t::start_writing(attotime tm)
{
- common_start(device, TYPE_UPD765B);
+ write_start_time = tm;
+ write_position = 0;
}
-static DEVICE_START( smc37c78 )
+void upd765_family_device::pll_t::stop_writing(floppy_image_device *floppy, attotime tm)
{
- common_start(device, TYPE_SMC37C78);
- // specified in documentation that by default is off
- upd765_t *fdc = get_safe_token(device);
- fdc->pool = false;
+ commit(floppy, tm);
+ write_start_time = attotime::never;
}
-static DEVICE_START( upd72065 )
+void upd765_family_device::pll_t::commit(floppy_image_device *floppy, attotime tm)
{
- common_start(device, TYPE_UPD72065);
+ if(write_start_time.is_never() || tm == write_start_time)
+ return;
+
+ if(floppy)
+ floppy->write_flux(write_start_time, tm, write_position, write_buffer);
+ write_start_time = tm;
+ write_position = 0;
}
-static DEVICE_RESET( upd765 )
+int upd765_family_device::pll_t::get_next_bit(attotime &tm, floppy_image_device *floppy, attotime limit)
{
- int i;
- upd765_t *fdc = get_safe_token(device);
- for (i = 0; i < 4; i++) {
- if (fdc->intf->floppy_drive_tags[i]!=NULL)
- {
- device_t *img;
+ attotime edge = floppy ? floppy->get_next_transition(ctime) : attotime::never;
- if (device->owner() != NULL)
- img = device->owner()->subdevice(fdc->intf->floppy_drive_tags[i]);
- else
- img = device->machine().device(fdc->intf->floppy_drive_tags[i]);
+ attotime next = ctime + period + phase_adjust;
- floppy_drive_set_controller(img, device);
- floppy_drive_set_ready_state_change_callback(img, upd765_set_ready_change_callback);
- }
- }
+#if 0
+ if(!edge.is_never())
+ fprintf(stderr, "ctime=%s, transition_time=%s, next=%s, pha=%s\n", tts(ctime).cstr(), tts(edge).cstr(), tts(next).cstr(), tts(phase_adjust).cstr());
+#endif
- upd765_reset(device,0);
-}
+ if(next > limit)
+ return -1;
-const device_type UPD765A = &device_creator<upd765a_device>;
+ ctime = next;
-upd765a_device::upd765a_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
- : device_t(mconfig, UPD765A, "UPD765A", tag, owner, clock)
-{
- m_token = global_alloc_clear(upd765_t);
-}
-upd765a_device::upd765a_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock)
- : device_t(mconfig, type, name, tag, owner, clock)
-{
- m_token = global_alloc_clear(upd765_t);
-}
+ if(edge.is_never() || edge >= next) {
+ // No transition in the window means 0 and pll in free run mode
+ phase_adjust = attotime::zero;
+ tm = next;
+ return 0;
+ }
-//-------------------------------------------------
-// device_config_complete - perform any
-// operations now that the configuration is
-// complete
-//-------------------------------------------------
+ // Transition in the window means 1, and the pll is adjusted
-void upd765a_device::device_config_complete()
-{
-}
+ attotime delta = edge - (next - period/2);
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
+ if(delta.seconds < 0)
+ phase_adjust = attotime::zero - ((attotime::zero - delta)*65)/100;
+ else
+ phase_adjust = (delta*65)/100;
-void upd765a_device::device_start()
-{
- DEVICE_START_NAME( upd765a )(this);
-}
+ if(delta < attotime::zero) {
+ if(freq_hist < 0)
+ freq_hist--;
+ else
+ freq_hist = -1;
+ } else if(delta > attotime::zero) {
+ if(freq_hist > 0)
+ freq_hist++;
+ else
+ freq_hist = 1;
+ } else
+ freq_hist = 0;
+
+ if(freq_hist) {
+ int afh = freq_hist < 0 ? -freq_hist : freq_hist;
+ if(afh > 1) {
+ attotime aper = attotime::from_double(period_adjust_base.as_double()*delta.as_double()/period.as_double());
+ period += aper;
+
+ if(period < min_period)
+ period = min_period;
+ else if(period > max_period)
+ period = max_period;
+ }
+ }
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
+ return 1;
+}
-void upd765a_device::device_reset()
+bool upd765_family_device::pll_t::write_next_bit(bool bit, attotime &tm, floppy_image_device *floppy, attotime limit)
{
- DEVICE_RESET_NAME( upd765 )(this);
-}
+ if(write_start_time.is_never()) {
+ write_start_time = ctime;
+ write_position = 0;
+ }
+ attotime etime = ctime + period;
+ if(etime > limit)
+ return true;
-const device_type UPD765B = &device_creator<upd765b_device>;
+ if(bit && write_position < ARRAY_LENGTH(write_buffer))
+ write_buffer[write_position++] = ctime + period/2;
-upd765b_device::upd765b_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
- : upd765a_device(mconfig, UPD765B, "UPD765B", tag, owner, clock)
-{
+ tm = etime;
+ ctime = etime;
+ return false;
}
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
-void upd765b_device::device_start()
+upd765a_device::upd765a_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : upd765_family_device(mconfig, UPD765A, "UPD765A", tag, owner, clock)
{
- DEVICE_START_NAME( upd765b )(this);
+ m_shortname = "upd765a";
+ dor_reset = 0x0c;
}
-
-const device_type SMC37C78 = &device_creator<smc37c78_device>;
-
-smc37c78_device::smc37c78_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
- : upd765a_device(mconfig, SMC37C78, "SMC37C78", tag, owner, clock)
+upd765b_device::upd765b_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : upd765_family_device(mconfig, UPD765B, "UPD765B", tag, owner, clock)
{
+ m_shortname = "upd765b";
+ dor_reset = 0x0c;
}
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
-void smc37c78_device::device_start()
+i8272a_device::i8272a_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : upd765_family_device(mconfig, I8272A, "I8272A", tag, owner, clock)
{
- DEVICE_START_NAME( smc37c78 )(this);
+ m_shortname = "i8272a";
+ dor_reset = 0x0c;
}
-
-const device_type UPD72065 = &device_creator<upd72065_device>;
-
-upd72065_device::upd72065_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
- : upd765a_device(mconfig, UPD72065, "UPD72065", tag, owner, clock)
+upd72065_device::upd72065_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : upd765_family_device(mconfig, UPD72065, "UPD72065", tag, owner, clock)
{
+ m_shortname = "upd72065";
+ dor_reset = 0x0c;
}
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
-void upd72065_device::device_start()
+smc37c78_device::smc37c78_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : upd765_family_device(mconfig, SMC37C78, "SMC37C78", tag, owner, clock)
{
- DEVICE_START_NAME( upd72065 )(this);
+ m_shortname = "smc37c78";
+ ready_connected = false;
+ select_connected = true;
}
+n82077aa_device::n82077aa_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : upd765_family_device(mconfig, N82077AA, "N82077AA", tag, owner, clock)
+{
+ m_shortname = "n82077aa";
+ ready_connected = false;
+ select_connected = true;
+}
+pc_fdc_superio_device::pc_fdc_superio_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : upd765_family_device(mconfig, PC_FDC_SUPERIO, "PC FDC SUPERIO", tag, owner, clock)
+{
+ m_shortname = "pc_fdc_superio";
+ ready_polled = false;
+ ready_connected = false;
+ select_connected = true;
+}
diff --git a/src/mess/machine/upd765.h b/src/mess/machine/upd765.h
index cac6bee3649..f7fd07b5506 100644
--- a/src/mess/machine/upd765.h
+++ b/src/mess/machine/upd765.h
@@ -1,215 +1,434 @@
-/***************************************************************************
+#ifndef __UPD765_F_H__
+#define __UPD765_F_H__
- machine/upd765.h
+#include "emu.h"
+#include "imagedev/floppy.h"
- Functions to emulate a NEC upd765/Intel 8272 compatible
- floppy disk controller
+/*
+ * ready = true if the ready line is physically connected to the floppy drive
+ * select = true if the fdc controls the floppy drive selection
+ * mode = MODE_AT, MODE_PS2 or MODE_M30 for the fdcs that have reset-time selection
+ */
-***************************************************************************/
+#define MCFG_UPD765A_ADD(_tag, _ready, _select) \
+ MCFG_DEVICE_ADD(_tag, UPD765A, 0) \
+ downcast<upd765a_device *>(device)->set_ready_line_connected(_ready); \
+ downcast<upd765a_device *>(device)->set_select_lines_connected(_select);
-#ifndef __UPD765_H__
-#define __UPD765_H__
+#define MCFG_UPD765B_ADD(_tag, _ready, _select) \
+ MCFG_DEVICE_ADD(_tag, UPD765B, 0) \
+ downcast<upd765b_device *>(device)->set_ready_line_connected(_ready); \
+ downcast<upd765b_device *>(device)->set_select_lines_connected(_select);
-#include "devcb.h"
-#include "imagedev/flopdrv.h"
+#define MCFG_I8272A_ADD(_tag, _ready) \
+ MCFG_DEVICE_ADD(_tag, I8272A, 0) \
+ downcast<i8272a_device *>(device)->set_ready_line_connected(_ready);
+#define MCFG_UPD72065_ADD(_tag, _ready, _select) \
+ MCFG_DEVICE_ADD(_tag, UPD72065, 0) \
+ downcast<upd72065_device *>(device)->set_ready_line_connected(_ready); \
+ downcast<upd72065_device *>(device)->set_select_lines_connected(_select);
-/***************************************************************************
- MACROS
-***************************************************************************/
+#define MCFG_SMC37C78_ADD(_tag) \
+ MCFG_DEVICE_ADD(_tag, SMC37C78, 0)
-class upd765a_device : public device_t
-{
-public:
- upd765a_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
- upd765a_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
- ~upd765a_device() { global_free(m_token); }
-
- // access to legacy token
- void *token() const { assert(m_token != NULL); return m_token; }
-protected:
- // device-level overrides
- virtual void device_config_complete();
- virtual void device_start();
- virtual void device_reset();
-private:
- // internal state
- void *m_token;
-};
-
-extern const device_type UPD765A;
-
-class upd765b_device : public upd765a_device
-{
-public:
- upd765b_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
-protected:
- // device-level overrides
- virtual void device_start();
-};
-
-extern const device_type UPD765B;
-
-class smc37c78_device : public upd765a_device
-{
-public:
- smc37c78_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
-protected:
- // device-level overrides
- virtual void device_start();
-};
+#define MCFG_N82077AA_ADD(_tag, _mode) \
+ MCFG_DEVICE_ADD(_tag, N82077AA, 0) \
+ downcast<n82077aa_device *>(device)->set_mode(_mode);
-extern const device_type SMC37C78;
+#define MCFG_PC_FDC_SUPERIO_ADD(_tag) \
+ MCFG_DEVICE_ADD(_tag, PC_FDC_SUPERIO, 0)
-class upd72065_device : public upd765a_device
-{
+/* Interface required for PC ISA wrapping */
+class pc_fdc_interface : public device_t {
public:
- upd72065_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
-protected:
- // device-level overrides
- virtual void device_start();
-};
-
-extern const device_type UPD72065;
-
-
-/***************************************************************************
- TYPE DEFINITIONS
-***************************************************************************/
-
-/* RDY pin connected state */
-enum UPD765_RDY_PIN
-{
- UPD765_RDY_PIN_NOT_CONNECTED = 0,
- UPD765_RDY_PIN_CONNECTED = 1
-};
-
-#define UPD765_DAM_DELETED_DATA 0x0f8
-#define UPD765_DAM_DATA 0x0fb
-
-typedef device_t *(*upd765_get_image_func)(device_t *device, int floppy_index);
-#define UPD765_GET_IMAGE(name) device_t *name(device_t *device, int floppy_index )
+ typedef delegate<void (bool state)> line_cb;
+ typedef delegate<UINT8 ()> byte_read_cb;
+ typedef delegate<void (UINT8)> byte_write_cb;
+ pc_fdc_interface(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock) : device_t(mconfig, type, name, tag, owner, clock) {}
-struct upd765_interface
-{
- /* interrupt issued */
- devcb_write_line out_int_func;
+ virtual void setup_intrq_cb(line_cb cb) = 0;
+ virtual void setup_drq_cb(line_cb cb) = 0;
- /* dma data request */
- devcb_write_line out_drq_func;
+ /* Note that the address map must cover and handle the whole 0-7
+ * range. The upd765, while conforming to the rest of the
+ * interface, is not eligible as a result.
+ */
- /* image lookup */
- upd765_get_image_func get_image;
+ virtual DECLARE_ADDRESS_MAP(map, 8) = 0;
- UPD765_RDY_PIN rdy_pin;
+ virtual UINT8 dma_r() = 0;
+ virtual void dma_w(UINT8 data) = 0;
- const char *floppy_drive_tags[4];
+ virtual void tc_w(bool val) = 0;
+ virtual UINT8 do_dir_r() = 0;
};
+class upd765_family_device : public pc_fdc_interface {
+public:
+ enum { MODE_AT, MODE_PS2, MODE_M30 };
-/***************************************************************************
- FUNCTION PROTOTYPES
-***************************************************************************/
-
-/* read of data register */
-DECLARE_READ8_DEVICE_HANDLER(upd765_data_r);
-/* write to data register */
-DECLARE_WRITE8_DEVICE_HANDLER(upd765_data_w);
-/* read of main status register */
-DECLARE_READ8_DEVICE_HANDLER(upd765_status_r);
+ upd765_family_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
-/* dma acknowledge with write */
-DECLARE_WRITE8_DEVICE_HANDLER(upd765_dack_w);
-/* dma acknowledge with read */
-DECLARE_READ8_DEVICE_HANDLER(upd765_dack_r);
+ void setup_intrq_cb(line_cb cb);
+ void setup_drq_cb(line_cb cb);
-/* reset upd765 */
-void upd765_reset(device_t *device, int);
+ virtual DECLARE_ADDRESS_MAP(map, 8) = 0;
-/* reset pin of upd765 */
-WRITE_LINE_DEVICE_HANDLER(upd765_reset_w);
+ DECLARE_READ8_MEMBER (sra_r);
+ DECLARE_READ8_MEMBER (srb_r);
+ DECLARE_READ8_MEMBER (dor_r);
+ DECLARE_WRITE8_MEMBER(dor_w);
+ DECLARE_READ8_MEMBER (tdr_r);
+ DECLARE_WRITE8_MEMBER(tdr_w);
+ DECLARE_READ8_MEMBER (msr_r);
+ DECLARE_WRITE8_MEMBER(dsr_w);
+ DECLARE_READ8_MEMBER (fifo_r);
+ DECLARE_WRITE8_MEMBER(fifo_w);
+ DECLARE_READ8_MEMBER (dir_r);
+ DECLARE_WRITE8_MEMBER(ccr_w);
-/* set upd765 terminal count input state */
-WRITE_LINE_DEVICE_HANDLER(upd765_tc_w);
+ virtual UINT8 do_dir_r();
-/* set upd765 ready input*/
-WRITE_LINE_DEVICE_HANDLER(upd765_ready_w);
+ UINT8 dma_r();
+ void dma_w(UINT8 data);
-void upd765_idle(device_t *device);
-void upd765_set_bad(device_t *device, int state);
+ // Same as the previous ones, but as memory-mappable members
+ DECLARE_READ8_MEMBER(mdma_r);
+ DECLARE_WRITE8_MEMBER(mdma_w);
-READ_LINE_DEVICE_HANDLER( upd765_int_r );
-READ_LINE_DEVICE_HANDLER( upd765_drq_r );
+ bool get_irq() const;
+ bool get_drq() const;
+ void tc_w(bool val);
+ void ready_w(bool val);
-/*********************/
-/* STATUS REGISTER 1 */
+ void set_rate(int rate); // rate in bps, to be used when the fdc is externally frequency-controlled
-/* this is set if a TC signal was not received after the sector data was read */
-#define UPD765_ST1_END_OF_CYLINDER (1<<7)
-/* this is set if the sector ID being searched for is not found */
-#define UPD765_ST1_NO_DATA (1<<2)
-/* set if disc is write protected and a write/format operation was performed */
-#define UPD765_ST1_NOT_WRITEABLE (1<<1)
+ void set_mode(int mode);
+ void set_ready_line_connected(bool ready);
+ void set_select_lines_connected(bool select);
+ void set_floppy(floppy_image_device *image);
-/*********************/
-/* STATUS REGISTER 2 */
+protected:
+ virtual void device_start();
+ virtual void device_reset();
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
+
+ enum {
+ TIMER_DRIVE_READY_POLLING = 4
+ };
+
+ enum {
+ PHASE_CMD, PHASE_EXEC, PHASE_RESULT
+ };
+
+ enum {
+ MSR_DB = 0x0f,
+ MSR_CB = 0x10,
+ MSR_EXM = 0x20,
+ MSR_DIO = 0x40,
+ MSR_RQM = 0x80,
+
+ ST0_UNIT = 0x07,
+ ST0_NR = 0x08,
+ ST0_EC = 0x10,
+ ST0_SE = 0x20,
+ ST0_FAIL = 0x40,
+ ST0_UNK = 0x80,
+ ST0_ABRT = 0xc0,
+
+ ST1_MA = 0x01,
+ ST1_NW = 0x02,
+ ST1_ND = 0x04,
+ ST1_OR = 0x10,
+ ST1_DE = 0x20,
+ ST1_EN = 0x80,
+
+ ST2_MD = 0x01,
+ ST2_BC = 0x02,
+ ST2_SN = 0x04,
+ ST2_SH = 0x08,
+ ST2_WC = 0x10,
+ ST2_DD = 0x20,
+ ST2_CM = 0x40,
+
+ ST3_UNIT = 0x07,
+ ST3_TS = 0x08,
+ ST3_T0 = 0x10,
+ ST3_RY = 0x20,
+ ST3_WP = 0x40,
+ ST3_FT = 0x80,
+
+ FIF_THR = 0x0f,
+ FIF_POLL = 0x10,
+ FIF_DIS = 0x20,
+ FIF_EIS = 0x40,
+
+ SPEC_ND = 0x0001,
+ };
+
+
+ enum {
+ // General "doing nothing" state
+ IDLE,
+
+ // Main states
+ RECALIBRATE,
+ SEEK,
+ READ_DATA,
+ WRITE_DATA,
+ READ_TRACK,
+ FORMAT_TRACK,
+ READ_ID,
+
+ // Sub-states
+ COMMAND_DONE,
+
+ SEEK_MOVE,
+ SEEK_WAIT_STEP_SIGNAL_TIME,
+ SEEK_WAIT_STEP_SIGNAL_TIME_DONE,
+ SEEK_WAIT_STEP_TIME,
+ SEEK_WAIT_STEP_TIME_DONE,
+ SEEK_DONE,
+
+ HEAD_LOAD_DONE,
+
+ WAIT_INDEX,
+ WAIT_INDEX_DONE,
+
+ SCAN_ID,
+ SCAN_ID_FAILED,
+
+ SECTOR_READ,
+ SECTOR_WRITTEN,
+ TC_DONE,
+
+ TRACK_DONE,
+
+ // Live states
+ SEARCH_ADDRESS_MARK_HEADER,
+ READ_HEADER_BLOCK_HEADER,
+ READ_DATA_BLOCK_HEADER,
+ READ_ID_BLOCK,
+ SEARCH_ADDRESS_MARK_DATA,
+ SEARCH_ADDRESS_MARK_DATA_FAILED,
+ READ_SECTOR_DATA,
+ READ_SECTOR_DATA_BYTE,
+
+ WRITE_SECTOR_SKIP_GAP2,
+ WRITE_SECTOR_SKIP_GAP2_BYTE,
+ WRITE_SECTOR_DATA,
+ WRITE_SECTOR_DATA_BYTE,
+
+ WRITE_TRACK_PRE_SECTORS,
+ WRITE_TRACK_PRE_SECTORS_BYTE,
+
+ WRITE_TRACK_SECTOR,
+ WRITE_TRACK_SECTOR_BYTE,
+
+ WRITE_TRACK_POST_SECTORS,
+ WRITE_TRACK_POST_SECTORS_BYTE,
+ };
+
+ struct pll_t {
+ attotime ctime, period, min_period, max_period, period_adjust_base, phase_adjust;
+
+ attotime write_start_time;
+ attotime write_buffer[32];
+ int write_position;
+ int freq_hist;
+
+ void set_clock(attotime period);
+ void reset(attotime when);
+ int get_next_bit(attotime &tm, floppy_image_device *floppy, attotime limit);
+ bool write_next_bit(bool bit, attotime &tm, floppy_image_device *floppy, attotime limit);
+ void start_writing(attotime tm);
+ void commit(floppy_image_device *floppy, attotime tm);
+ void stop_writing(floppy_image_device *floppy, attotime tm);
+ };
+
+ struct floppy_info {
+ emu_timer *tm;
+ floppy_image_device *dev;
+ int id;
+ int main_state, sub_state;
+ int dir, counter;
+ UINT8 pcn;
+ bool irq_seek, live, index, ready, irq_polled;
+ };
+
+ struct live_info {
+ enum { PT_NONE, PT_CRC_1, PT_CRC_2 };
+
+ attotime tm;
+ int state, next_state;
+ floppy_info *fi;
+ UINT16 shift_reg;
+ UINT16 crc;
+ int bit_counter, byte_counter, previous_type;
+ bool data_separator_phase, data_bit_context;
+ UINT8 data_reg;
+ UINT8 idbuf[6];
+ pll_t pll;
+ };
+
+ static int rates[4];
+
+ bool ready_connected, ready_polled, select_connected;
+
+ bool external_ready;
+
+ int mode;
+ int main_phase;
+
+ live_info cur_live, checkpoint_live;
+ line_cb intrq_cb, drq_cb;
+ bool cur_irq, data_irq, drq, internal_drq, tc, tc_done;
+ floppy_info flopi[4];
+
+ int fifo_pos, fifo_expected, command_pos, result_pos;
+ bool fifo_write;
+ UINT8 dor, dsr, msr, fifo[16], command[16], result[16];
+ UINT8 st0, st1, st2, st3;
+ UINT8 fifocfg, dor_reset;
+ UINT16 spec;
+ int sector_size;
+ int cur_rate;
+
+ emu_timer *poll_timer;
+
+ static astring tts(attotime t);
+ astring ttsn();
+
+ enum {
+ C_CONFIGURE,
+ C_FORMAT_TRACK,
+ C_PERPENDICULAR,
+ C_READ_DATA,
+ C_READ_ID,
+ C_READ_TRACK,
+ C_RECALIBRATE,
+ C_SEEK,
+ C_SENSE_DRIVE_STATUS,
+ C_SENSE_INTERRUPT_STATUS,
+ C_SPECIFY,
+ C_WRITE_DATA,
+
+ C_INVALID,
+ C_INCOMPLETE,
+ };
+
+ void delay_cycles(emu_timer *tm, int cycles);
+ void check_irq();
+ void fifo_expect(int size, bool write);
+ void fifo_push(UINT8 data, bool internal);
+ UINT8 fifo_pop(bool internal);
+ void set_drq(bool state);
+ bool get_ready(int fid);
+
+ void enable_transfer();
+ void disable_transfer();
+ int calc_sector_size(UINT8 size);
+
+ void run_drive_ready_polling();
+
+ int check_command();
+ void start_command(int cmd);
+ void command_end(floppy_info &fi, bool data_completion);
+
+ void recalibrate_start(floppy_info &fi);
+ void seek_start(floppy_info &fi);
+ void seek_continue(floppy_info &fi);
+
+ void read_data_start(floppy_info &fi);
+ void read_data_continue(floppy_info &fi);
+
+ void write_data_start(floppy_info &fi);
+ void write_data_continue(floppy_info &fi);
+
+ void read_track_start(floppy_info &fi);
+ void read_track_continue(floppy_info &fi);
+
+ void format_track_start(floppy_info &fi);
+ void format_track_continue(floppy_info &fi);
+
+ void read_id_start(floppy_info &fi);
+ void read_id_continue(floppy_info &fi);
+
+ void general_continue(floppy_info &fi);
+ void index_callback(floppy_image_device *floppy, int state);
+ bool sector_matches() const;
+
+ void live_start(floppy_info &fi, int live_state);
+ void live_abort();
+ void checkpoint();
+ void rollback();
+ void live_delay(int state);
+ void live_sync();
+ void live_run(attotime limit = attotime::never);
+ void live_write_raw(UINT16 raw);
+ void live_write_mfm(UINT8 mfm);
+
+ bool read_one_bit(attotime limit);
+ bool write_one_bit(attotime limit);
+};
-/* C parameter specified did not match C value read from disc */
-#define UPD765_ST2_WRONG_CYLINDER (1<<4)
-/* C parameter specified did not match C value read from disc, and C read from disc was 0x0ff */
-#define UPD765_ST2_BAD_CYLINDER (1<<1)
-/* this is set if the FDC encounters a Deleted Data Mark when executing a read data
-command, or FDC encounters a Data Mark when executing a read deleted data command */
-#define UPD765_ST2_CONTROL_MARK (1<<6)
+class upd765a_device : public upd765_family_device {
+public:
+ upd765a_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
-/***************************************************************************
- DEVICE CONFIGURATION MACROS
-***************************************************************************/
+ virtual DECLARE_ADDRESS_MAP(map, 8);
+};
-#define MCFG_UPD765A_ADD(_tag, _intrf) \
- MCFG_DEVICE_ADD(_tag, UPD765A, 0) \
- MCFG_DEVICE_CONFIG(_intrf)
+class upd765b_device : public upd765_family_device {
+public:
+ upd765b_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
-#define MCFG_UPD765A_MODIFY(_tag, _intrf) \
- MCFG_DEVICE_MODIFY(_tag) \
- MCFG_DEVICE_CONFIG(_intrf)
+ virtual DECLARE_ADDRESS_MAP(map, 8);
+};
-#define MCFG_UPD765A_REMOVE(_tag) \
- MCFG_DEVICE_REMOVE(_tag)
+class i8272a_device : public upd765_family_device {
+public:
+ i8272a_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
-#define MCFG_UPD765B_ADD(_tag, _intrf) \
- MCFG_DEVICE_ADD(_tag, UPD765B, 0) \
- MCFG_DEVICE_CONFIG(_intrf)
+ virtual DECLARE_ADDRESS_MAP(map, 8);
+};
-#define MCFG_UPD765B_MODIFY(_tag, _intrf) \
- MCFG_DEVICE_MODIFY(_tag) \
- MCFG_DEVICE_CONFIG(_intrf)
+class smc37c78_device : public upd765_family_device {
+public:
+ smc37c78_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
-#define MCFG_UPD765B_REMOVE(_tag) \
- MCFG_DEVICE_REMOVE(_tag)
+ virtual DECLARE_ADDRESS_MAP(map, 8);
+};
-#define MCFG_SMC37C78_ADD(_tag, _intrf) \
- MCFG_DEVICE_ADD(_tag, SMC37C78, 0) \
- MCFG_DEVICE_CONFIG(_intrf)
+class upd72065_device : public upd765_family_device {
+public:
+ upd72065_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
-#define MCFG_SMC37C78_MODIFY(_tag, _intrf) \
- MCFG_DEVICE_MODIFY(_tag) \
- MCFG_DEVICE_CONFIG(_intrf)
+ virtual DECLARE_ADDRESS_MAP(map, 8);
+};
-#define MCFG_SMC37C78_REMOVE(_tag) \
- MCFG_DEVICE_REMOVE(_tag)
+class n82077aa_device : public upd765_family_device {
+public:
+ n82077aa_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
-#define MCFG_UPD72065_ADD(_tag, _intrf) \
- MCFG_DEVICE_ADD(_tag, UPD72065, 0) \
- MCFG_DEVICE_CONFIG(_intrf)
+ virtual DECLARE_ADDRESS_MAP(map, 8);
+};
-#define MCFG_UPD72065_MODIFY(_tag, _intrf) \
- MCFG_DEVICE_MODIFY(_tag) \
- MCFG_DEVICE_CONFIG(_intrf)
+class pc_fdc_superio_device : public upd765_family_device {
+public:
+ pc_fdc_superio_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
-#define MCFG_UPD72065_REMOVE(_tag) \
- MCFG_DEVICE_REMOVE(_tag)
+ virtual DECLARE_ADDRESS_MAP(map, 8);
+};
+extern const device_type UPD765A;
+extern const device_type UPD765B;
+extern const device_type I8272A;
+extern const device_type UPD72065;
+extern const device_type SMC37C78;
+extern const device_type N82077AA;
+extern const device_type PC_FDC_SUPERIO;
-#endif /* __UPD765_H__ */
+#endif