diff options
Diffstat (limited to 'src/mess/machine/pc_fdc.c')
-rw-r--r-- | src/mess/machine/pc_fdc.c | 194 |
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 |