summaryrefslogtreecommitdiffstatshomepage
path: root/src/mess/machine/pc_fdc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mess/machine/pc_fdc.c')
-rw-r--r--src/mess/machine/pc_fdc.c194
1 files changed, 193 insertions, 1 deletions
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