From 1c7adc2338dd5618a8381b68adb734508b1e73ad Mon Sep 17 00:00:00 2001 From: 68bit Date: Wed, 31 Jul 2019 11:26:04 +1000 Subject: swtpc09: update, use the SS-30 bus, get these working. Add support for the SS-30 bus. The DC5 FDC, MPS2, PIA-IDE and MPT have been added to the SS-30 bus and are split out. A separate floppy format has been added for UniFLEX, and the FLEX format has been improved. These formats should be usable now, and have been lightly tested. The banked memory was not implemented correctly and has been updated. The DMAF2 and DMAF3 FDCs are still implemented in the swtpc09 device, but have been updated. These belong on the SS-50 bus, but there is no SS-50 bus yet - still on the TODO list. The PIA IDE has been implemented on the SS-30 bus, and updated to get it working, and the swtpc09i machine is promoted to working. Have been able to boot this from a FLEX hard disk image, and it also boots FLEX using the DC5 FDC. Tested swtpc09 running FLEX with DMAF2 support. Tested swtpc09d3 running UniFLEX and it seems to run well. The hard disk support is still TODO, but added a reference to the WD1000 documentation. Did not have a UniFLEX image on hand to test the swtpc09u, but have tested the DMAF2 under FLEX and UniFLEX using DMAF3 so it's probably ok or close. Had no documentation for the DMAF3. --- src/mame/drivers/swtpc09.cpp | 526 +++++++++++++++++++++++++++++++----------- src/mame/includes/swtpc09.h | 117 ++++++---- src/mame/machine/swtpc09.cpp | 530 ++++++++++++++++++++++++++++--------------- 3 files changed, 804 insertions(+), 369 deletions(-) diff --git a/src/mame/drivers/swtpc09.cpp b/src/mame/drivers/swtpc09.cpp index 5e7f3fd0c72..9760351c7f4 100644 --- a/src/mame/drivers/swtpc09.cpp +++ b/src/mame/drivers/swtpc09.cpp @@ -1,5 +1,5 @@ // license:BSD-3-Clause -// copyright-holders:Robert Justice +// copyright-holders:Robert Justice,68bit /************************************************************************** SWTPC S/09 Mess driver @@ -7,25 +7,28 @@ Emulates four different fixed combinations of hardware 1. swtpc09 - MP-09 with SBUG rom, MP-ID, MP-S2, DMF2. + MP-09 with SBUG rom, MP-ID, MP-S2, MP-T, DMAF2. Will boot Flex operating system 2. swtpc09i - MP-09 with SBUG rom + HDrom, MP-ID, MP-S2, DMF2, PIAIDE. + MP-09 with SBUG rom + HDrom, MP-ID, MP-S2, MP-T, DMAF2, PIAIDE. Will boot Flex operating system TODO: finish ide part and get this one working. 3. swtpc09u - MP-09 with UniBUG rom, MP-ID, MP-S2, DMF2. + MP-09 with UniBUG rom, MP-ID, MP-S2, DMAF2. Will boot UniFlex operating system 4. swtpc09d3 - MP-09 with UniBUG U3 rom, MP-ID, MP-S2, DMF3. + MP-09 with UniBUG U3 rom, MP-ID, MP-S2, DMAF3. Will boot UniFlex operating system - TODO: add Harddisk support, DMF3 has WD1000 interface + TODO: add Harddisk support, DMAF3 has WD1000 interface ***************************************************************************/ #include "emu.h" #include "includes/swtpc09.h" +#include "bus/ss50/interface.h" +#include "machine/input_merger.h" #include "formats/flex_dsk.h" +#include "formats/uniflex_dsk.h" /************************************************************************** @@ -36,24 +39,29 @@ E000 - E003 S2 MC6850 ACIA1 (used for UniFlex console) E004 - E007 S2 MC6850 ACIA2 (used for Flex console) + E014 - E015 DC5 Control reg. + E016 - E017 DC5 Control reg. 2 + E018 - E01B DC5 WD2797 FDC + E040 - E043 MPT MC6821 PIA + MK5009 timer/counter E080 - E08F MPID MC6821 PIA E090 - E09F MPID MC6840 PTM - F000 - F01F DMF2 MC6844 DMAC - F020 - F023 DMF2 WD1791 FDC - F024 - F03F DMF2 Drive select register - F040 - F041 DMF2 DMA Address register + F000 - F01F DMAF2 MC6844 DMAC + F020 - F023 DMAF2 WD1791 FDC + F024 - F03F DMAF2 Drive select register + F040 - F041 DMAF2 DMA Address register F800 - FFFF ROM FFF0 - FFFF DAT RAM (only for writes) - for DMF3 version - F000 - F01F DMF3 MC6844 DMAC - F020 - F023 DMF3 WD1791 FDC - F024 - F024 DMF3 Drive select register - F025 - F025 DMF3 DMA Address register - F040 - F04F DMF3 6522 VIA + for DMAF3 version + F000 - F01F DMAF3 MC6844 DMAC + F020 - F023 DMAF3 WD1791 FDC + F024 - F024 DMAF3 Drive select register + F025 - F025 DMAF3 DMA Address register + F030 - F03F DMAF3 WD1000 + F040 - F04F DMAF3 6522 VIA ***************************************************************************/ @@ -62,225 +70,477 @@ void swtpc09_state::mp09_mem(address_map &map) { - map(0x0000, 0xfeff).rw(FUNC(swtpc09_state::main_r), FUNC(swtpc09_state::main_w)); - map(0xff00, 0xffff).rom().region("maincpu", 0xff00); + map(0x0000, 0xffff).rw(FUNC(swtpc09_state::main_r), FUNC(swtpc09_state::main_w)); map(0xff00, 0xff0f).mirror(0xf0).writeonly().share("dat"); } -void swtpc09_state::flex_dmf2_mem(address_map &map) +void swtpc09_state::flex_dmaf2_mem(address_map &map) { map(0x00000, 0xfffff).ram(); // by default everything is ram, 1MB ram emulated - map(0xe000, 0xe003).mirror(0xf0000).noprw(); - map(0xe004, 0xe005).mirror(0xf0000).rw(m_acia, FUNC(acia6850_device::read), FUNC(acia6850_device::write)); - map(0xe080, 0xe083).mirror(0xf000c).rw(m_pia, FUNC(pia6821_device::read), FUNC(pia6821_device::write)); - map(0xe090, 0xe097).mirror(0xf0008).rw(m_ptm, FUNC(ptm6840_device::read), FUNC(ptm6840_device::write)); - map(0xe0a0, 0xefff).mirror(0xf0000).noprw(); - map(0xf000, 0xf01f).mirror(0xf0000).rw(FUNC(swtpc09_state::m6844_r), FUNC(swtpc09_state::m6844_w)); - map(0xf020, 0xf023).mirror(0xf0000).rw(m_fdc, FUNC(fd1793_device::read), FUNC(fd1793_device::write)); - map(0xf024, 0xf03f).mirror(0xf0000).rw(FUNC(swtpc09_state::dmf2_control_reg_r), FUNC(swtpc09_state::dmf2_control_reg_w)); - //AM_RANGE(0xf042, 0xf7ff) AM_MIRROR(0xf0000) AM_NOP - map(0xf800, 0xffff).mirror(0xf0000).rom().region("maincpu", 0xf800); + map(0xfe000, 0xfe7ff).rw(FUNC(swtpc09_state::unmapped_r), FUNC(swtpc09_state::unmapped_w)); + + // 0xfe004, 0xfe005 ACIA + map(0xfe000, 0xfe00f).rw("io0", FUNC(ss50_interface_port_device::read), FUNC(ss50_interface_port_device::write)); + map(0xfe010, 0xfe01f).rw("io1", FUNC(ss50_interface_port_device::read), FUNC(ss50_interface_port_device::write)); + map(0xfe020, 0xfe02f).rw("io2", FUNC(ss50_interface_port_device::read), FUNC(ss50_interface_port_device::write)); + map(0xfe030, 0xfe03f).rw("io3", FUNC(ss50_interface_port_device::read), FUNC(ss50_interface_port_device::write)); + map(0xfe040, 0xfe04f).rw("io4", FUNC(ss50_interface_port_device::read), FUNC(ss50_interface_port_device::write)); + map(0xfe050, 0xfe05f).rw("io5", FUNC(ss50_interface_port_device::read), FUNC(ss50_interface_port_device::write)); + map(0xfe060, 0xfe06f).rw("io6", FUNC(ss50_interface_port_device::read), FUNC(ss50_interface_port_device::write)); + map(0xfe070, 0xfe07f).rw("io7", FUNC(ss50_interface_port_device::read), FUNC(ss50_interface_port_device::write)); + + // MPID + map(0xfe080, 0xfe083).mirror(0xc).rw(m_pia, FUNC(pia6821_device::read), FUNC(pia6821_device::write)); + map(0xfe090, 0xfe097).mirror(0x8).rw(m_ptm, FUNC(ptm6840_device::read), FUNC(ptm6840_device::write)); + // DMAF2 + map(0xff000, 0xff01f).rw(FUNC(swtpc09_state::m6844_r), FUNC(swtpc09_state::m6844_w)); + map(0xff020, 0xff023).rw(FUNC(swtpc09_state::dmaf2_fdc_r), FUNC(swtpc09_state::dmaf2_fdc_w)); + map(0xff024, 0xff03f).rw(FUNC(swtpc09_state::dmaf2_control_reg_r), FUNC(swtpc09_state::dmaf2_control_reg_w)); + + map(0xff800, 0xfffff).rom().region("bankdev", 0xff800); } -void swtpc09_state::flex_dc4_piaide_mem(address_map &map) +void swtpc09_state::flex_dc5_piaide_mem(address_map &map) { - map(0x00000, 0x0efff).ram(); // by default everything is ram, 1MB ram emulated - map(0x10000, 0x1efff).ram(); // avoid the s09ram though - map(0xe000, 0xe003).mirror(0xf0000).noprw(); - map(0xe004, 0xe005).mirror(0xf0000).rw(m_acia, FUNC(acia6850_device::read), FUNC(acia6850_device::write)); - map(0xe014, 0xe014).mirror(0xf0000).w(FUNC(swtpc09_state::dc4_control_reg_w)); - map(0xe018, 0xe01b).mirror(0xf0000).rw(m_fdc, FUNC(fd1793_device::read), FUNC(fd1793_device::write)); - //AM_RANGE(0xe01c, 0xe05f) AM_MIRROR(0xf0000) AM_NOP - map(0xe060, 0xe063).mirror(0xf000c).rw(m_piaide, FUNC(pia6821_device::read), FUNC(pia6821_device::write)); - //AM_RANGE(0xe070, 0xe07f) AM_MIRROR(0xf0000) AM_NOP - map(0xe080, 0xe083).mirror(0xf000c).rw(m_pia, FUNC(pia6821_device::read), FUNC(pia6821_device::write)); - map(0xe090, 0xe097).mirror(0xf0008).rw(m_ptm, FUNC(ptm6840_device::read), FUNC(ptm6840_device::write)); - //AM_RANGE(0xe0a0, 0xe7ff) AM_MIRROR(0xf0000) AM_NOP - map(0xe800, 0xefff).mirror(0xf0000).rom().region("maincpu", 0xe800); //piaide rom - //AM_RANGE(0xf000, 0xf01f) AM_MIRROR(0xf0000) AM_READWRITE(m6844_r, m6844_w) - //AM_RANGE(0xf020, 0xf023) AM_MIRROR(0xf0000) AM_DEVREADWRITE("fdc", fd1793_device, read, write) - //AM_RANGE(0xf024, 0xf03f) AM_MIRROR(0xf0000) AM_READWRITE(dmf2_control_reg_r, dmf2_control_reg_w) - //AM_RANGE(0xf040, 0xf041) AM_MIRROR(0xf0000) AM_READWRITE(dmf2_dma_address_reg_r, dmf2_dma_address_reg_w) - map(0xf000, 0xf7ff).mirror(0xf0000).ram().share("s09ram"); // 2k ram for piaide on s09 board - map(0xf800, 0xffff).mirror(0xf0000).rom().region("maincpu", 0xf800); + map(0x00000, 0xfffff).ram(); // by default everything is ram, 1MB ram emulated + map(0xfe000, 0xfe7ff).rw(FUNC(swtpc09_state::unmapped_r), FUNC(swtpc09_state::unmapped_w)); + + // 0xfe004, 0xfe005 ACIA + map(0xfe000, 0xfe00f).rw("io0", FUNC(ss50_interface_port_device::read), FUNC(ss50_interface_port_device::write)); + // 0xfe014 0xfe018-0xfe01b DC5 FDC + map(0xfe010, 0xfe01f).rw("io1", FUNC(ss50_interface_port_device::read), FUNC(ss50_interface_port_device::write)); + map(0xfe020, 0xfe02f).rw("io2", FUNC(ss50_interface_port_device::read), FUNC(ss50_interface_port_device::write)); + map(0xfe030, 0xfe03f).rw("io3", FUNC(ss50_interface_port_device::read), FUNC(ss50_interface_port_device::write)); + map(0xfe040, 0xfe04f).rw("io4", FUNC(ss50_interface_port_device::read), FUNC(ss50_interface_port_device::write)); + map(0xfe050, 0xfe05f).rw("io5", FUNC(ss50_interface_port_device::read), FUNC(ss50_interface_port_device::write)); + // PIA IDE + map(0xfe060, 0xfe06f).rw("io6", FUNC(ss50_interface_port_device::read), FUNC(ss50_interface_port_device::write)); + map(0xfe070, 0xfe07f).rw("io7", FUNC(ss50_interface_port_device::read), FUNC(ss50_interface_port_device::write)); + + // MPID + map(0xfe080, 0xfe083).mirror(0xc).rw(m_pia, FUNC(pia6821_device::read), FUNC(pia6821_device::write)); + map(0xfe090, 0xfe097).mirror(0x8).rw(m_ptm, FUNC(ptm6840_device::read), FUNC(ptm6840_device::write)); + + // TODO How does this mapping change with the bank changes? + map(0xfe800, 0xfefff).rom().region("bankdev", 0xfe800); //piaide rom + + map(0xff800, 0xfffff).rom().region("bankdev", 0xff800); } -void swtpc09_state::uniflex_dmf2_mem(address_map &map) +void swtpc09_state::uniflex_dmaf2_mem(address_map &map) { map(0x00000, 0xfffff).ram(); // by default everything is ram, 1MB ram emulated - map(0xe000, 0xe001).mirror(0xf0000).rw(m_acia, FUNC(acia6850_device::read), FUNC(acia6850_device::write)); - map(0xe002, 0xe07f).mirror(0xf0000).noprw(); - map(0xe080, 0xe083).mirror(0xf000c).rw(m_pia, FUNC(pia6821_device::read), FUNC(pia6821_device::write)); - map(0xe090, 0xe097).mirror(0xf0008).rw(m_ptm, FUNC(ptm6840_device::read), FUNC(ptm6840_device::write)); - map(0xe0a0, 0xefff).mirror(0xf0000).noprw(); - map(0xf000, 0xf01f).mirror(0xf0000).rw(FUNC(swtpc09_state::m6844_r), FUNC(swtpc09_state::m6844_w)); - map(0xf020, 0xf023).mirror(0xf0000).rw(m_fdc, FUNC(fd1793_device::read), FUNC(fd1793_device::write)); - map(0xf024, 0xf03f).mirror(0xf0000).rw(FUNC(swtpc09_state::dmf2_control_reg_r), FUNC(swtpc09_state::dmf2_control_reg_w)); - //AM_RANGE(0xf042, 0xf7ff) AM_MIRROR(0xf0000) AM_NOP - map(0xf800, 0xffff).mirror(0xf0000).rom().region("maincpu", 0xf800); + map(0xfe000, 0xfffff).rw(FUNC(swtpc09_state::unmapped_r), FUNC(swtpc09_state::unmapped_w)); + + // 0xfe000, 0xfe001 ACIA + map(0xfe000, 0xfe00f).rw("io0", FUNC(ss50_interface_port_device::read), FUNC(ss50_interface_port_device::write)); + map(0xfe010, 0xfe01f).rw("io1", FUNC(ss50_interface_port_device::read), FUNC(ss50_interface_port_device::write)); + map(0xfe020, 0xfe02f).rw("io2", FUNC(ss50_interface_port_device::read), FUNC(ss50_interface_port_device::write)); + map(0xfe030, 0xfe03f).rw("io3", FUNC(ss50_interface_port_device::read), FUNC(ss50_interface_port_device::write)); + map(0xfe040, 0xfe04f).rw("io4", FUNC(ss50_interface_port_device::read), FUNC(ss50_interface_port_device::write)); + map(0xfe050, 0xfe05f).rw("io5", FUNC(ss50_interface_port_device::read), FUNC(ss50_interface_port_device::write)); + map(0xfe060, 0xfe06f).rw("io6", FUNC(ss50_interface_port_device::read), FUNC(ss50_interface_port_device::write)); + map(0xfe070, 0xfe07f).rw("io7", FUNC(ss50_interface_port_device::read), FUNC(ss50_interface_port_device::write)); + + // MPID + map(0xfe080, 0xfe083).mirror(0xc).rw(m_pia, FUNC(pia6821_device::read), FUNC(pia6821_device::write)); + map(0xfe090, 0xfe097).mirror(0x8).rw(m_ptm, FUNC(ptm6840_device::read), FUNC(ptm6840_device::write)); + + // DMAF2 + map(0xff000, 0xff01f).rw(FUNC(swtpc09_state::m6844_r), FUNC(swtpc09_state::m6844_w)); + map(0xff020, 0xff023).rw(FUNC(swtpc09_state::dmaf2_fdc_r), FUNC(swtpc09_state::dmaf2_fdc_w)); + map(0xff024, 0xff03f).rw(FUNC(swtpc09_state::dmaf2_control_reg_r), FUNC(swtpc09_state::dmaf2_control_reg_w)); + + map(0xff800, 0xfffff).rom().region("bankdev", 0xff800); } -void swtpc09_state::uniflex_dmf3_mem(address_map &map) +void swtpc09_state::uniflex_dmaf3_mem(address_map &map) { map(0x00000, 0xfffff).ram(); // by default everything is ram, 1MB ram emulated - map(0xe000, 0xe001).mirror(0xf0000).rw(m_acia, FUNC(acia6850_device::read), FUNC(acia6850_device::write)); - map(0xe002, 0xe07f).mirror(0xf0000).noprw(); - map(0xe080, 0xe083).mirror(0xf000c).rw(m_pia, FUNC(pia6821_device::read), FUNC(pia6821_device::write)); - map(0xe090, 0xe097).mirror(0xf0008).rw(m_ptm, FUNC(ptm6840_device::read), FUNC(ptm6840_device::write)); - map(0xe0a0, 0xefff).mirror(0xf0000).noprw(); - map(0xf000, 0xf01f).mirror(0xf0000).rw(FUNC(swtpc09_state::m6844_r), FUNC(swtpc09_state::m6844_w)); - map(0xf020, 0xf023).mirror(0xf0000).rw(m_fdc, FUNC(fd1793_device::read), FUNC(fd1793_device::write)); - map(0xf024, 0xf024).mirror(0xf0000).rw(FUNC(swtpc09_state::dmf3_control_reg_r), FUNC(swtpc09_state::dmf3_control_reg_w)); - map(0xf025, 0xf025).mirror(0xf0000).rw(FUNC(swtpc09_state::dmf3_dma_address_reg_r), FUNC(swtpc09_state::dmf3_dma_address_reg_w)); - //AM_RANGE(0xf030, 0xf03f) AM_MIRROR(0xf0000) AM_NOP - map(0xf040, 0xf04f).mirror(0xf0000).m(m_via, FUNC(via6522_device::map)); - //AM_RANGE(0xf050, 0xf7ff) AM_MIRROR(0xf0000) AM_NOP - map(0xf800, 0xffff).mirror(0xf0000).rom().region("maincpu", 0xf800); + map(0xfe000, 0xfffff).rw(FUNC(swtpc09_state::unmapped_r), FUNC(swtpc09_state::unmapped_w)); + + // 0xfe000, 0xfe001 ACIA + map(0xfe000, 0xfe00f).rw("io0", FUNC(ss50_interface_port_device::read), FUNC(ss50_interface_port_device::write)); + map(0xfe010, 0xfe01f).rw("io1", FUNC(ss50_interface_port_device::read), FUNC(ss50_interface_port_device::write)); + map(0xfe020, 0xfe02f).rw("io2", FUNC(ss50_interface_port_device::read), FUNC(ss50_interface_port_device::write)); + map(0xfe030, 0xfe03f).rw("io3", FUNC(ss50_interface_port_device::read), FUNC(ss50_interface_port_device::write)); + map(0xfe040, 0xfe04f).rw("io4", FUNC(ss50_interface_port_device::read), FUNC(ss50_interface_port_device::write)); + map(0xfe050, 0xfe05f).rw("io5", FUNC(ss50_interface_port_device::read), FUNC(ss50_interface_port_device::write)); + map(0xfe060, 0xfe06f).rw("io6", FUNC(ss50_interface_port_device::read), FUNC(ss50_interface_port_device::write)); + map(0xfe070, 0xfe07f).rw("io7", FUNC(ss50_interface_port_device::read), FUNC(ss50_interface_port_device::write)); + + // MPID + map(0xfe080, 0xfe083).mirror(0xc).rw(m_pia, FUNC(pia6821_device::read), FUNC(pia6821_device::write)); + map(0xfe090, 0xfe097).mirror(0x8).rw(m_ptm, FUNC(ptm6840_device::read), FUNC(ptm6840_device::write)); + + // DMAF3 + map(0xff000, 0xff01f).rw(FUNC(swtpc09_state::m6844_r), FUNC(swtpc09_state::m6844_w)); + map(0xff020, 0xff023).rw(FUNC(swtpc09_state::dmaf3_fdc_r), FUNC(swtpc09_state::dmaf3_fdc_w)); + map(0xff024, 0xff024).rw(FUNC(swtpc09_state::dmaf3_control_reg_r), FUNC(swtpc09_state::dmaf3_control_reg_w)); + map(0xff025, 0xff025).rw(FUNC(swtpc09_state::dmaf3_dma_address_reg_r), FUNC(swtpc09_state::dmaf3_dma_address_reg_w)); + map(0xff040, 0xff04f).m(m_via, FUNC(via6522_device::map)); + + // DMAF3 WD1000 + map(0xff030, 0xff03f).rw(FUNC(swtpc09_state::dmaf3_wd_r), FUNC(swtpc09_state::dmaf3_wd_w)); + + map(0xff800, 0xfffff).rom().region("bankdev", 0xff800); } /* Input ports */ static INPUT_PORTS_START( swtpc09 ) + // The MP09 was available in 4MHz or 8MHz XTALs, running the 6809 at + // 1MHz or 2MHz respectively. Also allow an overclock option. + // + // Run the 6809 at 2MHz (an 8MHz XTAL) so that manual polling of FDC can + // keep up with higher rate operation. The MPU09 did have the option of + // 1MHz or 2MHz operation. + PORT_START("maincpu_clock") + PORT_CONFNAME(0xffffff, 2000000, "CPU clock") + PORT_CONFSETTING(1000000, "1.0 MHz") + PORT_CONFSETTING(2000000, "2.0 MHz") + PORT_CONFSETTING(4000000, "4.0 MHz") + + // The DMAF2/3 clock can be jumpered selected for 1 or 2MHz, for 5.24" + // and 8" drives. Some other options are also provided here. + // + // single or double density 5.24" - 1.0MHz + // 'standard' 3.5" - 1.2MHz + // 3.5" hd - 2.0MHz + // 8" 360rpm - 2.4MHz + PORT_START("fdc_clock") + PORT_DIPNAME(0xffffff, 2000000, "DMAF2/3 FDC clock") + PORT_DIPSETTING(1000000, "1.0 MHz") + PORT_DIPSETTING(1200000, "1.2 MHz") + PORT_DIPSETTING(2000000, "2.0 MHz") + PORT_DIPSETTING(2400000, "2.4 MHz") + + // The MP-ID board has jumpers to vary the baud rates generated. The + // most useful is the Low/High rate jumper that provide a four times + // rate increase. + PORT_START("baud_rate_high") + PORT_DIPNAME(0x1, 0, "High baud rate") + PORT_DIPSETTING(0, "Low (x1)") + PORT_DIPSETTING(1, "High (x4)") + + // Debug aid to hard code the density. The FLEX format uses single + // density for track zero. Many virtual disks 'fix' the format to be + // purely double density and often without properly implementing + // driver support for that. This setting is an aid to report + // unexpected usage, and it attempts to correct that. It is possible + // to patch the software to work with these pure double density disks. + PORT_START("floppy_expected_density") + PORT_CONFNAME(0xff, 0, "DMAF2/3 expected density") + PORT_CONFSETTING(0, "-") + PORT_CONFSETTING(1, "single density") + PORT_CONFSETTING(2, "double density, with single density track zero") + PORT_CONFSETTING(3, "double density") + + // Debug aid, to check that the sector head or side is set as expected + // for the sector ID being read for the FLEX floppy disk format. Many + // FLEX disk images were developed for vitural machines that have + // little regard for the actual head and can work off the sector ID + // and their drivers can set the head incorrectly. E.g. a disk with 18 + // sectors per side might have a drive set to switch heads for sectors + // above 10. Another issue is that double density disk images are + // often 'fixed' so that they are pure double density without being + // single density onthe first track, and the drivers might still set + // the head based track zero being single density. This aid is not + // intended to be a substitute for fixing the drivers but it does help + // work through the issues while patching the disks. + PORT_START("floppy_expected_sectors") + PORT_CONFNAME(0xff, 0, "DMAF2/3 expected sectors per side") + PORT_CONFSETTING(0, "-") + PORT_CONFSETTING(10, "10") // 5 1/4" single density 256B + PORT_CONFSETTING(15, "15") // 8" single density 256B + PORT_CONFSETTING(18, "18") // 5 1/4" double density 256B + PORT_CONFSETTING(26, "26") // 8" double density 256B + PORT_CONFSETTING(36, "36") // 3.5" 1.4M QD 256B + // The track zero expected sectors if different from the above. FLEX + // 6800 disks did format track zero in single density and if the + // driver sticks to that and if using a double density disk then set a + // single density size here. + PORT_START("floppy_track_zero_expected_sectors") + PORT_CONFNAME(0xff, 0, "DMAF2/3 track zero expected sectors per side") + PORT_CONFSETTING(0, "-") + PORT_CONFSETTING(10, "10") // 5 1/4" single density 256B + PORT_CONFSETTING(15, "15") // 8" single density 256B + PORT_CONFSETTING(18, "18") // 5 1/4" double density 256B + PORT_CONFSETTING(26, "26") // 8" double density 256B + PORT_CONFSETTING(36, "36") // 3.5" 1.4M QD 256B + + PORT_START("sbug_double_density") + PORT_CONFNAME(0x1, 0, "SBUG patch for double density (SSO) disk boot") + PORT_CONFSETTING(0, "No - single density") + PORT_CONFSETTING(1, "Yes - double density") + + // The PIA IDE PROM includes initialization code that patches FLEX + // after the disk boot code has loaded FLEX, and then it jumps to + // 0xc850 to cold start FLEX. Have seen 0xcd00 being the cold start + // address, so add an option to patch the PROM for that. + PORT_START("piaide_flex_boot_cd00") + PORT_CONFNAME(0x1, 0, "PIA IDE PROM patch FLEX entry to 0xcd00") + PORT_CONFSETTING(0, "No - FLEX entry 0xc850") + PORT_CONFSETTING(1, "Yes - FLEX entry 0xcd00") + INPUT_PORTS_END -FLOPPY_FORMATS_MEMBER( swtpc09_state::floppy_formats ) + +static DEVICE_INPUT_DEFAULTS_START( dc5 ) + DEVICE_INPUT_DEFAULTS("address_mode", 0xf, 1) +DEVICE_INPUT_DEFAULTS_END + + +FLOPPY_FORMATS_MEMBER( swtpc09_state::floppy_flex_formats ) + FLOPPY_MFI_FORMAT, FLOPPY_FLEX_FORMAT FLOPPY_FORMATS_END +FLOPPY_FORMATS_MEMBER( swtpc09_state::floppy_uniflex_formats ) + FLOPPY_MFI_FORMAT, + FLOPPY_UNIFLEX_FORMAT +FLOPPY_FORMATS_END + + // todo: implement floppy controller cards as slot devices and do this properly -static void swtpc09_floppies(device_slot_interface &device) +static void swtpc09_flex_floppies(device_slot_interface &device) { - device.option_add("sssd", FLOPPY_525_SSSD); // flex 40 trks ss sd 5.25 - device.option_add("sssd35", FLOPPY_525_SSSD_35T); // flex 35 trks ss sd 5.25 - device.option_add("ssdd", FLOPPY_525_SSDD); // flex 40 trks ss dd 5.25 - device.option_add("dd", FLOPPY_525_DD); // flex 40 trks ds dd 5.25 - device.option_add("8dssd", FLOPPY_8_DSSD); // UNIFlex 8 inch ds sd - device.option_add("8dsdd", FLOPPY_8_DSDD); // UNIFlex 8 inch ds dd - device.option_add("35hd", FLOPPY_35_HD); // flex 1.44mb disk from swtpc emu (emulator only?) + device.option_add("sssd35", FLOPPY_525_SSSD_35T); // 35 trks ss sd 5.25 + device.option_add("sssd", FLOPPY_525_SSSD); // 40 trks ss sd 5.25 + device.option_add("dssd35", FLOPPY_525_SD_35T); // 35 trks ds sd 5.25 + device.option_add("dssd", FLOPPY_525_SD); // 40 trks ds sd 5.25 + device.option_add("ssdd", FLOPPY_525_SSDD); // 40 trks ss dd 5.25 + device.option_add("dd", FLOPPY_525_DD); // 40 trks ds dd 5.25 + device.option_add("ssqd", FLOPPY_525_SSQD); // 80 trks ss dd 5.25 + device.option_add("qd", FLOPPY_525_QD); // 80 trks ds dd 5.25 + device.option_add("8sssd", FLOPPY_8_SSSD); // 77 trks ss sd 8" + device.option_add("8dssd", FLOPPY_8_DSSD); // 77 trks ds sd 8" + device.option_add("8ssdd", FLOPPY_8_SSDD); // 77 trks ss dd 8" + device.option_add("8dsdd", FLOPPY_8_DSDD); // 77 trks ds dd 8" + device.option_add("35hd", FLOPPY_35_HD); // 1.44mb disk } +static void swtpc09_uniflex_floppies(device_slot_interface &device) +{ + device.option_add("8dssd", FLOPPY_8_DSSD); // 8 inch ds sd + device.option_add("8dsdd", FLOPPY_8_DSDD); // 8 inch ds dd + } + /*************************************************************************** Machine definitions ****************************************************************************/ /* Machine driver */ -/* MPU09, MPID, MPS2 DMF2 */ +/* MPU09, MPID, MPS2 */ void swtpc09_state::swtpc09_base(machine_config &config) { /* basic machine hardware */ - MC6809(config, m_maincpu, 4_MHz_XTAL); + MC6809(config, m_maincpu, 8_MHz_XTAL); m_maincpu->set_addrmap(AS_PROGRAM, &swtpc09_state::mp09_mem); ADDRESS_MAP_BANK(config, m_bankdev, 0); m_bankdev->set_endianness(ENDIANNESS_BIG); m_bankdev->set_data_width(8); m_bankdev->set_addr_width(20); - m_bankdev->set_addrmap(AS_PROGRAM, &swtpc09_state::flex_dmf2_mem); - + m_bankdev->set_addrmap(AS_PROGRAM, &swtpc09_state::flex_dmaf2_mem); + + // IO0 at 0xe000 is used for the MP-S2 ACIA. + ss50_interface_port_device &io0(SS50_INTERFACE(config, "io0", ss50_default_2rs_devices, nullptr)); + io0.irq_cb().set("mainirq", FUNC(input_merger_device::in_w<0>)); + io0.firq_cb().set("mainfirq", FUNC(input_merger_device::in_w<0>)); + // IO1 at 0xe010 is used for the DC5 FDC. + ss50_interface_port_device &io1(SS50_INTERFACE(config, "io1", ss50_default_2rs_devices, nullptr)); + io1.irq_cb().set("mainirq", FUNC(input_merger_device::in_w<1>)); + io1.firq_cb().set("mainfirq", FUNC(input_merger_device::in_w<1>)); + ss50_interface_port_device &io2(SS50_INTERFACE(config, "io2", ss50_default_2rs_devices, nullptr)); + io2.irq_cb().set("mainirq", FUNC(input_merger_device::in_w<2>)); + io2.firq_cb().set("mainfirq", FUNC(input_merger_device::in_w<2>)); + ss50_interface_port_device &io3(SS50_INTERFACE(config, "io3", ss50_default_2rs_devices, nullptr)); + io3.irq_cb().set("mainirq", FUNC(input_merger_device::in_w<3>)); + io3.firq_cb().set("mainfirq", FUNC(input_merger_device::in_w<3>)); + ss50_interface_port_device &io4(SS50_INTERFACE(config, "io4", ss50_default_2rs_devices, nullptr)); + io4.irq_cb().set("mainirq", FUNC(input_merger_device::in_w<4>)); + io4.firq_cb().set("mainfirq", FUNC(input_merger_device::in_w<4>)); + ss50_interface_port_device &io5(SS50_INTERFACE(config, "io5", ss50_default_2rs_devices, nullptr)); + io5.irq_cb().set("mainirq", FUNC(input_merger_device::in_w<5>)); + io5.firq_cb().set("mainfirq", FUNC(input_merger_device::in_w<5>)); + // IO6 at 0xe060 is used for PIA-IDE + ss50_interface_port_device &io6(SS50_INTERFACE(config, "io6", ss50_default_2rs_devices, nullptr)); + io6.irq_cb().set("mainirq", FUNC(input_merger_device::in_w<6>)); + io6.firq_cb().set("mainfirq", FUNC(input_merger_device::in_w<6>)); + ss50_interface_port_device &io7(SS50_INTERFACE(config, "io7", ss50_default_2rs_devices, nullptr)); + io7.irq_cb().set("mainirq", FUNC(input_merger_device::in_w<7>)); + io7.firq_cb().set("mainfirq", FUNC(input_merger_device::in_w<7>)); + + // IO8 at 0xe080 is used internally by the MPID board PIA. PIA6821(config, m_pia, 0); m_pia->readpa_handler().set(FUNC(swtpc09_state::pia0_a_r)); m_pia->readca1_handler().set(FUNC(swtpc09_state::pia0_ca1_r)); m_pia->irqa_handler().set(FUNC(swtpc09_state::pia0_irq_a)); + // IO9 at 0xe090 is used internally by the MPID board 6840 timer. PTM6840(config, m_ptm, 2000000); m_ptm->set_external_clocks(50, 0, 50); m_ptm->o1_callback().set(FUNC(swtpc09_state::ptm_o1_callback)); m_ptm->o3_callback().set(FUNC(swtpc09_state::ptm_o3_callback)); m_ptm->irq_callback().set(FUNC(swtpc09_state::ptm_irq)); - rs232_port_device &rs232(RS232_PORT(config, "rs232", default_rs232_devices, "terminal")); - rs232.rxd_handler().set(m_acia, FUNC(acia6850_device::write_rxd)); - rs232.cts_handler().set(m_acia, FUNC(acia6850_device::write_cts)); - - ACIA6850(config, m_acia, 0); - m_acia->txd_handler().set("rs232", FUNC(rs232_port_device::write_txd)); - m_acia->rts_handler().set("rs232", FUNC(rs232_port_device::write_rts)); - m_acia->irq_handler().set(FUNC(swtpc09_state::acia_interrupt)); - + // MP-ID baud rate generator MC14411(config, m_brg, 1.8432_MHz_XTAL); - m_brg->out_f<1>().set(m_acia, FUNC(acia6850_device::write_txc)); - m_brg->out_f<1>().append(m_acia, FUNC(acia6850_device::write_rxc)); - - FD1793(config, m_fdc, 1_MHz_XTAL); - FLOPPY_CONNECTOR(config, "fdc:0", swtpc09_floppies, "dd", swtpc09_state::floppy_formats); - FLOPPY_CONNECTOR(config, "fdc:1", swtpc09_floppies, "dd", swtpc09_state::floppy_formats); - FLOPPY_CONNECTOR(config, "fdc:2", swtpc09_floppies, "dd", swtpc09_state::floppy_formats); - FLOPPY_CONNECTOR(config, "fdc:3", swtpc09_floppies, "dd", swtpc09_state::floppy_formats); + // 9600b / 38400b + m_brg->out_f<1>().set("io0", FUNC(ss50_interface_port_device::f150_9600_w)); + m_brg->out_f<1>().append("io1", FUNC(ss50_interface_port_device::f150_9600_w)); + m_brg->out_f<1>().append("io2", FUNC(ss50_interface_port_device::f150_9600_w)); + m_brg->out_f<1>().append("io3", FUNC(ss50_interface_port_device::f150_9600_w)); + m_brg->out_f<1>().append("io4", FUNC(ss50_interface_port_device::f150_9600_w)); + m_brg->out_f<1>().append("io5", FUNC(ss50_interface_port_device::f150_9600_w)); + m_brg->out_f<1>().append("io6", FUNC(ss50_interface_port_device::f150_9600_w)); + m_brg->out_f<1>().append("io7", FUNC(ss50_interface_port_device::f150_9600_w)); + // 4800b / 19200b + m_brg->out_f<3>().set("io0", FUNC(ss50_interface_port_device::f600_4800_w)); + m_brg->out_f<3>().append("io1", FUNC(ss50_interface_port_device::f600_4800_w)); + m_brg->out_f<3>().append("io2", FUNC(ss50_interface_port_device::f600_4800_w)); + m_brg->out_f<3>().append("io3", FUNC(ss50_interface_port_device::f600_4800_w)); + m_brg->out_f<3>().append("io4", FUNC(ss50_interface_port_device::f600_4800_w)); + m_brg->out_f<3>().append("io5", FUNC(ss50_interface_port_device::f600_4800_w)); + m_brg->out_f<3>().append("io6", FUNC(ss50_interface_port_device::f600_4800_w)); + m_brg->out_f<3>().append("io7", FUNC(ss50_interface_port_device::f600_4800_w)); + // 1200b / 4800b + m_brg->out_f<7>().set("io0", FUNC(ss50_interface_port_device::f600_1200_w)); + m_brg->out_f<7>().append("io1", FUNC(ss50_interface_port_device::f600_1200_w)); + m_brg->out_f<7>().append("io2", FUNC(ss50_interface_port_device::f600_1200_w)); + m_brg->out_f<7>().append("io3", FUNC(ss50_interface_port_device::f600_1200_w)); + m_brg->out_f<7>().append("io4", FUNC(ss50_interface_port_device::f600_1200_w)); + m_brg->out_f<7>().append("io5", FUNC(ss50_interface_port_device::f600_1200_w)); + m_brg->out_f<7>().append("io6", FUNC(ss50_interface_port_device::f600_1200_w)); + m_brg->out_f<7>().append("io7", FUNC(ss50_interface_port_device::f600_1200_w)); + // 300b / 1200b + m_brg->out_f<9>().set("io0", FUNC(ss50_interface_port_device::f300_w)); + m_brg->out_f<9>().append("io1", FUNC(ss50_interface_port_device::f300_w)); + m_brg->out_f<9>().append("io2", FUNC(ss50_interface_port_device::f300_w)); + m_brg->out_f<9>().append("io3", FUNC(ss50_interface_port_device::f300_w)); + m_brg->out_f<9>().append("io4", FUNC(ss50_interface_port_device::f300_w)); + m_brg->out_f<9>().append("io5", FUNC(ss50_interface_port_device::f300_w)); + m_brg->out_f<9>().append("io6", FUNC(ss50_interface_port_device::f300_w)); + m_brg->out_f<9>().append("io7", FUNC(ss50_interface_port_device::f300_w)); + // 110b / 440b + m_brg->out_f<13>().set("io0", FUNC(ss50_interface_port_device::f110_w)); + m_brg->out_f<13>().append("io1", FUNC(ss50_interface_port_device::f110_w)); + m_brg->out_f<13>().append("io2", FUNC(ss50_interface_port_device::f110_w)); + m_brg->out_f<13>().append("io3", FUNC(ss50_interface_port_device::f110_w)); + m_brg->out_f<13>().append("io4", FUNC(ss50_interface_port_device::f110_w)); + m_brg->out_f<13>().append("io5", FUNC(ss50_interface_port_device::f110_w)); + m_brg->out_f<13>().append("io6", FUNC(ss50_interface_port_device::f110_w)); + m_brg->out_f<13>().append("io7", FUNC(ss50_interface_port_device::f110_w)); + + INPUT_MERGER_ANY_HIGH(config, "mainirq").output_handler().set(FUNC(swtpc09_state::io_irq_w)); + INPUT_MERGER_ANY_HIGH(config, "mainfirq").output_handler().set_inputline(m_maincpu, M6809_FIRQ_LINE); + + subdevice("io0")->set_default_option("mps2"); } +/* MPU09, MPID, MPS2, DMAF2 */ void swtpc09_state::swtpc09(machine_config &config) { swtpc09_base(config); + + // DMAF2 + FD1797(config, m_fdc, 2000000); + FLOPPY_CONNECTOR(config, "fdc:0", swtpc09_flex_floppies, "dd", swtpc09_state::floppy_flex_formats).enable_sound(true); + FLOPPY_CONNECTOR(config, "fdc:1", swtpc09_flex_floppies, "dd", swtpc09_state::floppy_flex_formats).enable_sound(true); + FLOPPY_CONNECTOR(config, "fdc:2", swtpc09_flex_floppies, "dd", swtpc09_state::floppy_flex_formats).enable_sound(true); + FLOPPY_CONNECTOR(config, "fdc:3", swtpc09_flex_floppies, "dd", swtpc09_state::floppy_flex_formats).enable_sound(true); + m_fdc->intrq_wr_callback().set(FUNC(swtpc09_state::fdc_intrq_w)); m_fdc->drq_wr_callback().set(FUNC(swtpc09_state::fdc_drq_w)); + m_fdc->sso_wr_callback().set(FUNC(swtpc09_state::fdc_sso_w)); } -/* MPU09, MPID, MPS2 DC4 PIAIDE*/ +/* MPU09, MPID, MPS2, DC5, MPT, PIAIDE*/ void swtpc09_state::swtpc09i(machine_config &config) { swtpc09_base(config); - m_bankdev->set_addrmap(AS_PROGRAM, &swtpc09_state::flex_dc4_piaide_mem); + m_bankdev->set_addrmap(AS_PROGRAM, &swtpc09_state::flex_dc5_piaide_mem); - PIA6821(config, "piaide", 0); - - /* TODO: add ide support, via add-on card driving IDE from a PIA */ + subdevice("io1")->set_default_option("dc5"); + subdevice("io1")->set_option_device_input_defaults("dc5", DEVICE_INPUT_DEFAULTS_NAME(dc5)); + subdevice("io4")->set_default_option("mpt"); + subdevice("io6")->set_default_option("piaide"); } void swtpc09_state::swtpc09u(machine_config &config) { - swtpc09(config); - m_bankdev->set_addrmap(AS_PROGRAM, &swtpc09_state::uniflex_dmf2_mem); + swtpc09_base(config); + m_bankdev->set_addrmap(AS_PROGRAM, &swtpc09_state::uniflex_dmaf2_mem); + + // DMAF2 + FD1797(config, m_fdc, 2400000); + FLOPPY_CONNECTOR(config, "fdc:0", swtpc09_uniflex_floppies, "8dsdd", swtpc09_state::floppy_uniflex_formats).enable_sound(true); + FLOPPY_CONNECTOR(config, "fdc:1", swtpc09_uniflex_floppies, "8dsdd", swtpc09_state::floppy_uniflex_formats).enable_sound(true); + FLOPPY_CONNECTOR(config, "fdc:2", swtpc09_uniflex_floppies, "8dsdd", swtpc09_state::floppy_uniflex_formats).enable_sound(true); + FLOPPY_CONNECTOR(config, "fdc:3", swtpc09_uniflex_floppies, "8dsdd", swtpc09_state::floppy_uniflex_formats).enable_sound(true); + + m_fdc->intrq_wr_callback().set(FUNC(swtpc09_state::fdc_intrq_w)); + m_fdc->drq_wr_callback().set(FUNC(swtpc09_state::fdc_drq_w)); + m_fdc->sso_wr_callback().set(FUNC(swtpc09_state::fdc_sso_w)); } -/* MPU09, MPID, MPS2 DMF3 */ +/* MPU09, MPID, MPS2 DMAF3 */ void swtpc09_state::swtpc09d3(machine_config &config) { swtpc09_base(config); - m_maincpu->set_clock(8_MHz_XTAL); m_pia->set_clock(2000000); - m_bankdev->set_addrmap(AS_PROGRAM, &swtpc09_state::uniflex_dmf3_mem); + m_bankdev->set_addrmap(AS_PROGRAM, &swtpc09_state::uniflex_dmaf3_mem); - /* video hardware */ - m_acia->irq_handler().set_inputline(m_maincpu, M6809_IRQ_LINE); + // DMAF3 + FD1797(config, m_fdc, 2400000); + FLOPPY_CONNECTOR(config, "fdc:0", swtpc09_uniflex_floppies, "8dsdd", swtpc09_state::floppy_uniflex_formats).enable_sound(true); + FLOPPY_CONNECTOR(config, "fdc:1", swtpc09_uniflex_floppies, "8dsdd", swtpc09_state::floppy_uniflex_formats).enable_sound(true); + FLOPPY_CONNECTOR(config, "fdc:2", swtpc09_uniflex_floppies, "8dsdd", swtpc09_state::floppy_uniflex_formats).enable_sound(true); + FLOPPY_CONNECTOR(config, "fdc:3", swtpc09_uniflex_floppies, "8dsdd", swtpc09_state::floppy_uniflex_formats).enable_sound(true); + + m_fdc->intrq_wr_callback().set(FUNC(swtpc09_state::fdc_intrq_w)); + m_fdc->drq_wr_callback().set(FUNC(swtpc09_state::fdc_drq_w)); + m_fdc->sso_wr_callback().set(FUNC(swtpc09_state::fdc_sso_w)); via6522_device &via(VIA6522(config, "via", 4_MHz_XTAL / 4)); - via.readpa_handler().set(FUNC(swtpc09_state::dmf3_via_read_porta)); - via.readpb_handler().set(FUNC(swtpc09_state::dmf3_via_read_portb)); - via.writepa_handler().set(FUNC(swtpc09_state::dmf3_via_write_porta)); - //via.ca1_handler().set(FUNC(swtpc09_state::dmf3_via_write_ca1)); - via.irq_handler().set(FUNC(swtpc09_state::dmf3_via_irq)); + via.readpa_handler().set(FUNC(swtpc09_state::dmaf3_via_read_porta)); + via.readpb_handler().set(FUNC(swtpc09_state::dmaf3_via_read_portb)); + via.writepa_handler().set(FUNC(swtpc09_state::dmaf3_via_write_porta)); + //via.ca1_handler().set(FUNC(swtpc09_state::dmaf3_via_write_ca1)); + via.irq_handler().set(FUNC(swtpc09_state::dmaf3_via_irq)); } /* ROM definition */ ROM_START( swtpc09 ) - ROM_REGION( 0x100000, "maincpu", 0 ) - ROM_LOAD ( "sbugh1-8.bin", 0xf800, 0x0800, CRC(10a045a7) SHA1(de547b77653951c7424a069520d52c5b0432e98d) ) + ROM_REGION( 0x100000, "bankdev", 0 ) + ROM_LOAD ( "sbugh1-8.bin", 0xff800, 0x0800, CRC(10a045a7) SHA1(de547b77653951c7424a069520d52c5b0432e98d) ) ROM_END ROM_START( swtpc09i ) - ROM_REGION( 0x100000, "maincpu", 0 ) - ROM_LOAD ( "hd-rom.bin", 0xe800, 0x0800, CRC(b898b4d7) SHA1(2806633eda7da4e9a243fc534f15526ee928b6bc) ) - ROM_LOAD ( "sbugh1-8.bin", 0xf800, 0x0800, CRC(10a045a7) SHA1(de547b77653951c7424a069520d52c5b0432e98d) ) + ROM_REGION( 0x100000, "bankdev", 0 ) + ROM_LOAD ( "hd-rom.bin", 0xfe800, 0x0800, CRC(b898b4d7) SHA1(2806633eda7da4e9a243fc534f15526ee928b6bc) ) + ROM_LOAD ( "sbugh1-8.bin", 0xff800, 0x0800, CRC(10a045a7) SHA1(de547b77653951c7424a069520d52c5b0432e98d) ) ROM_END ROM_START( swtpc09u ) - ROM_REGION( 0x100000, "maincpu", 0 ) - ROM_LOAD ( "unibug.bin", 0xf800, 0x0800, CRC(92e1cbf2) SHA1(db00f17ee9accdbfa1775fe0162d3556159b8e70) ) + ROM_REGION( 0x100000, "bankdev", 0 ) + ROM_LOAD ( "unibug.bin", 0xff800, 0x00800, CRC(92e1cbf2) SHA1(db00f17ee9accdbfa1775fe0162d3556159b8e70) ) ROM_END ROM_START( swtpc09d3 ) - ROM_REGION( 0x100000, "maincpu", 0 ) - ROM_LOAD ( "uos3.bin", 0xf800, 0x0800, CRC(e95eb3e0) SHA1(3e971d3b7e143bc87e4b506e18a8c928c089c25a) ) + ROM_REGION( 0x100000, "bankdev", 0 ) + ROM_LOAD ( "uos3.bin", 0xff800, 0x00800, CRC(e95eb3e0) SHA1(3e971d3b7e143bc87e4b506e18a8c928c089c25a) ) ROM_END /* Driver */ // YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS COMP( 1980, swtpc09, 0, 0, swtpc09, swtpc09, swtpc09_state, init_swtpc09, "SWTPC", "swtpc S/09 Sbug", MACHINE_NO_SOUND_HW ) -COMP( 1980, swtpc09i, swtpc09, 0, swtpc09i, swtpc09, swtpc09_state, init_swtpc09i, "SWTPC", "swtpc S/09 Sbug + piaide", MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW ) -COMP( 1980, swtpc09u, swtpc09, 0, swtpc09u, swtpc09, swtpc09_state, init_swtpc09u, "SWTPC", "swtpc S/09 UNIBug + DMF2", MACHINE_NO_SOUND_HW ) -COMP( 1980, swtpc09d3, swtpc09, 0, swtpc09d3, swtpc09, swtpc09_state, init_swtpc09d3, "SWTPC", "swtpc S/09 UNIBug + DMF3", MACHINE_NO_SOUND_HW ) +COMP( 1980, swtpc09i, swtpc09, 0, swtpc09i, swtpc09, swtpc09_state, init_swtpc09i, "SWTPC", "swtpc S/09 Sbug + piaide", MACHINE_NO_SOUND_HW ) +COMP( 1980, swtpc09u, swtpc09, 0, swtpc09u, swtpc09, swtpc09_state, init_swtpc09u, "SWTPC", "swtpc S/09 UNIBug + DMAF2", MACHINE_NO_SOUND_HW ) +COMP( 1980, swtpc09d3, swtpc09, 0, swtpc09d3, swtpc09, swtpc09_state, init_swtpc09d3, "SWTPC", "swtpc S/09 UNIBug + DMAF3", MACHINE_NO_SOUND_HW ) diff --git a/src/mame/includes/swtpc09.h b/src/mame/includes/swtpc09.h index 17178c7434c..8dc3b9169e7 100644 --- a/src/mame/includes/swtpc09.h +++ b/src/mame/includes/swtpc09.h @@ -1,5 +1,5 @@ // license:BSD-3-Clause -// copyright-holders:Robert Justice +// copyright-holders:Robert Justice,68bit /*************************************************************************** swtpc09 include file Robert Justice ,2009-2014 @@ -17,14 +17,10 @@ #include "imagedev/floppy.h" #include "machine/6840ptm.h" #include "machine/6821pia.h" -#include "machine/6850acia.h" #include "machine/6522via.h" #include "imagedev/harddriv.h" -#include "machine/idectrl.h" #include "machine/bankdev.h" #include "machine/mc14411.h" -#include "bus/rs232/rs232.h" - class swtpc09_state : public driver_device @@ -36,18 +32,22 @@ public: , m_brg(*this, "brg") , m_pia(*this, "pia") , m_ptm(*this, "ptm") - , m_acia(*this, "acia") , m_fdc(*this, "fdc") , m_floppy0(*this, "fdc:0") , m_floppy1(*this, "fdc:1") , m_floppy2(*this, "fdc:2") , m_floppy3(*this, "fdc:3") , m_via(*this, "via") - , m_piaide(*this, "piaide") - , m_harddisk(*this, "harddisk") - , m_ide(*this, "ide") , m_dat(*this, "dat") , m_bankdev(*this, "bankdev") + , m_maincpu_clock(*this, "maincpu_clock") + , m_fdc_clock(*this, "fdc_clock") + , m_baud_rate_high(*this, "baud_rate_high") + , m_floppy_expected_density(*this, "floppy_expected_density") + , m_floppy_expected_sectors(*this, "floppy_expected_sectors") + , m_floppy_track_zero_expected_sectors(*this, "floppy_track_zero_expected_sectors") + , m_sbug_double_density(*this, "sbug_double_density") + , m_piaide_flex_boot_cd00(*this, "piaide_flex_boot_cd00") { } void swtpc09_base(machine_config &config); @@ -62,42 +62,46 @@ public: void init_swtpc09d3(); private: - DECLARE_FLOPPY_FORMATS(floppy_formats); + DECLARE_FLOPPY_FORMATS(floppy_flex_formats); + DECLARE_FLOPPY_FORMATS(floppy_uniflex_formats); DECLARE_READ8_MEMBER(pia0_a_r); DECLARE_READ8_MEMBER(pia0_ca1_r); DECLARE_WRITE_LINE_MEMBER( pia0_irq_a ); + DECLARE_WRITE_LINE_MEMBER(io_irq_w); + DECLARE_WRITE_LINE_MEMBER( ptm_o1_callback ); DECLARE_WRITE_LINE_MEMBER( ptm_o3_callback ); DECLARE_WRITE_LINE_MEMBER( ptm_irq ); - DECLARE_WRITE_LINE_MEMBER( acia_interrupt ); - DECLARE_WRITE_LINE_MEMBER( fdc_intrq_w ); DECLARE_WRITE_LINE_MEMBER( fdc_drq_w ); + DECLARE_WRITE_LINE_MEMBER( fdc_sso_w ); - DECLARE_READ8_MEMBER( dmf3_via_read_porta ); - DECLARE_READ8_MEMBER( dmf3_via_read_portb ); - DECLARE_WRITE8_MEMBER( dmf3_via_write_porta ); - DECLARE_WRITE_LINE_MEMBER( dmf3_via_irq ); + DECLARE_READ8_MEMBER( dmaf3_via_read_porta ); + DECLARE_READ8_MEMBER( dmaf3_via_read_portb ); + DECLARE_WRITE8_MEMBER( dmaf3_via_write_porta ); + DECLARE_WRITE_LINE_MEMBER( dmaf3_via_irq ); - DECLARE_READ8_MEMBER(piaide_a_r); - DECLARE_READ8_MEMBER(piaide_b_r); - DECLARE_WRITE8_MEMBER(piaide_a_w); - DECLARE_WRITE8_MEMBER(piaide_b_w); + TIMER_CALLBACK_MEMBER(floppy_motor_callback); - DECLARE_READ8_MEMBER ( dmf2_dma_address_reg_r ); - DECLARE_WRITE8_MEMBER ( dmf2_dma_address_reg_w ); - DECLARE_READ8_MEMBER ( dmf2_control_reg_r ); - DECLARE_WRITE8_MEMBER ( dmf2_control_reg_w ); + DECLARE_READ8_MEMBER( dmaf2_fdc_r ); + DECLARE_WRITE8_MEMBER( dmaf2_fdc_w ); + DECLARE_READ8_MEMBER ( dmaf2_dma_address_reg_r ); + DECLARE_WRITE8_MEMBER ( dmaf2_dma_address_reg_w ); + DECLARE_READ8_MEMBER ( dmaf2_control_reg_r ); + DECLARE_WRITE8_MEMBER ( dmaf2_control_reg_w ); - DECLARE_READ8_MEMBER ( dmf3_dma_address_reg_r ); - DECLARE_WRITE8_MEMBER ( dmf3_dma_address_reg_w ); - DECLARE_READ8_MEMBER ( dmf3_control_reg_r ); - DECLARE_WRITE8_MEMBER ( dmf3_control_reg_w ); + DECLARE_READ8_MEMBER( dmaf3_fdc_r ); + DECLARE_WRITE8_MEMBER( dmaf3_fdc_w ); + DECLARE_READ8_MEMBER ( dmaf3_dma_address_reg_r ); + DECLARE_WRITE8_MEMBER ( dmaf3_dma_address_reg_w ); + DECLARE_READ8_MEMBER ( dmaf3_control_reg_r ); + DECLARE_WRITE8_MEMBER ( dmaf3_control_reg_w ); - DECLARE_WRITE8_MEMBER ( dc4_control_reg_w ); + DECLARE_READ8_MEMBER( dmaf3_wd_r ); + DECLARE_WRITE8_MEMBER( dmaf3_wd_w ); DECLARE_WRITE8_MEMBER(dat_w); DECLARE_READ8_MEMBER(main_r); @@ -106,44 +110,63 @@ private: DECLARE_READ8_MEMBER ( m6844_r ); DECLARE_WRITE8_MEMBER ( m6844_w ); - void flex_dc4_piaide_mem(address_map &map); - void flex_dmf2_mem(address_map &map); + DECLARE_READ8_MEMBER ( unmapped_r ); + DECLARE_WRITE8_MEMBER ( unmapped_w ); + + void flex_dc5_piaide_mem(address_map &map); + void flex_dmaf2_mem(address_map &map); void mp09_mem(address_map &map); - void uniflex_dmf2_mem(address_map &map); - void uniflex_dmf3_mem(address_map &map); + void uniflex_dmaf2_mem(address_map &map); + void uniflex_dmaf3_mem(address_map &map); virtual void machine_start() override; + virtual void machine_reset() override; void swtpc09_fdc_dma_transfer(); void swtpc09_irq_handler(uint8_t peripheral, uint8_t state); + void floppy_motor_trigger(); + + void validate_floppy_side(uint8_t cmd); + uint8_t validate_fdc_sector_size(uint8_t cmd); + uint8_t validate_fdc_dden(uint8_t dden); + offs_t dat_translate(offs_t offset) const; required_device m_maincpu; required_device m_brg; required_device m_pia; required_device m_ptm; - required_device m_acia; - required_device m_fdc; - required_device m_floppy0; - required_device m_floppy1; - required_device m_floppy2; - required_device m_floppy3; + + optional_device m_fdc; + optional_device m_floppy0; + optional_device m_floppy1; + optional_device m_floppy2; + optional_device m_floppy3; + optional_device m_via; - optional_device m_piaide; - optional_device m_harddisk; - optional_device m_ide; required_shared_ptr m_dat; required_device m_bankdev; + required_ioport m_maincpu_clock; + required_ioport m_fdc_clock; + required_ioport m_baud_rate_high; + required_ioport m_floppy_expected_density; + required_ioport m_floppy_expected_sectors; + required_ioport m_floppy_track_zero_expected_sectors; + required_ioport m_sbug_double_density; + required_ioport m_piaide_flex_boot_cd00; uint8_t m_pia_counter; // this is the counter on pia porta - uint8_t m_fdc_dma_address_reg; // dmf2 or dmf3 dma extended address reg + + uint8_t m_fdc_dma_address_reg; // dmaf2 or dmaf3 dma extended address reg uint8_t m_system_type; // flag to indicate hw and rom combination uint8_t m_fdc_status; // for floppy controller - uint8_t m_via_ca1_input; // dmf3 fdc interrupt is connected here - uint8_t m_dmf3_via_porta; - uint8_t m_piaide_porta; - uint8_t m_piaide_portb; + int m_floppy_motor_on; + emu_timer *m_floppy_motor_timer; + floppy_image_device *m_fdc_floppy; // Current selected floppy. + uint8_t m_fdc_side; // Current floppy side. + uint8_t m_via_ca1_input; // dmaf3 fdc interrupt is connected here + uint8_t m_dmaf3_via_porta; uint8_t m_active_interrupt; uint8_t m_interrupt; diff --git a/src/mame/machine/swtpc09.cpp b/src/mame/machine/swtpc09.cpp index 64ddd7703aa..2f6643e4878 100644 --- a/src/mame/machine/swtpc09.cpp +++ b/src/mame/machine/swtpc09.cpp @@ -1,5 +1,5 @@ // license:BSD-3-Clause -// copyright-holders:Robert Justice +// copyright-holders:Robert Justice,68bit /*************************************************************************** swtpc09 machine file Robert Justice ,2009-2014 @@ -10,21 +10,38 @@ #include "includes/swtpc09.h" #define DMAC_IRQ 0x01 // interrupt handler IDs -#define ACIA_IRQ 0x02 #define PTM_IRQ 0x04 #define PIA_IRQ 0x08 #define FDC_IRQ 0x10 #define VIA_IRQ 0x20 +#define IO_IRQ 0x40 -#define FLEX_DMF2 1 // system type flags -#define UNIFLEX_DMF2 2 -#define UNIFLEX_DMF3 3 -#define FLEX_DC4_PIAIDE 4 +#define FLEX_DMAF2 1 // system type flags +#define UNIFLEX_DMAF2 2 +#define UNIFLEX_DMAF3 3 +#define FLEX_DC5_PIAIDE 4 -#define VERBOSE 0 -#define LOG(x) do { if (VERBOSE) logerror x; } while (0) +READ8_MEMBER(swtpc09_state::unmapped_r) +{ + if (!machine().side_effects_disabled()) { + logerror("%s Unmapped read from addr %04x\n", machine().describe_context(), offset); + } + return 0; +} +WRITE8_MEMBER(swtpc09_state::unmapped_w) +{ + logerror("%s Unmapped write to addr %04x with data %02x\n", machine().describe_context(), offset, data); +} + +WRITE_LINE_MEMBER(swtpc09_state::io_irq_w) +{ + if (state) + swtpc09_irq_handler(IO_IRQ, ASSERT_LINE); + else + swtpc09_irq_handler(IO_IRQ, CLEAR_LINE); +} /******* MC6840 PTM on MPID Board *******/ @@ -72,70 +89,203 @@ WRITE_LINE_MEMBER( swtpc09_state::pia0_irq_a ) } -/******* MC6850 ACIA on MPS2 *******/ +/* Shared floppy support. */ -WRITE_LINE_MEMBER( swtpc09_state::acia_interrupt ) +void swtpc09_state::floppy_motor_trigger() { - if (state) + m_floppy0->get_device()->mon_w(CLEAR_LINE); + m_floppy1->get_device()->mon_w(CLEAR_LINE); + m_floppy2->get_device()->mon_w(CLEAR_LINE); + m_floppy3->get_device()->mon_w(CLEAR_LINE); + m_floppy_motor_timer->adjust(attotime::from_msec(30000)); + m_floppy_motor_on = 1; +} + +TIMER_CALLBACK_MEMBER(swtpc09_state::floppy_motor_callback) +{ + m_floppy0->get_device()->mon_w(ASSERT_LINE); + m_floppy1->get_device()->mon_w(ASSERT_LINE); + m_floppy2->get_device()->mon_w(ASSERT_LINE); + m_floppy3->get_device()->mon_w(ASSERT_LINE); + m_floppy_motor_on = 0; +} + +// Hack On a FDC command write, check that the floppy side is as expected +// given the track and sector. This check is performed for the type II and III +// commands. The floppy side is modified if necessary. +void swtpc09_state::validate_floppy_side(uint8_t cmd) +{ + if ((cmd & 0xe1) == 0x80 || (cmd & 0xe0) == 0xa0 || + (cmd & 0xf9) == 0xc0 || (cmd & 0xf9) == 0xe0 || + (cmd & 0xf9) == 0xf0) { - swtpc09_irq_handler(ACIA_IRQ, ASSERT_LINE); - logerror("swtpc09_acia_irq_assert\n"); + uint32_t expected_sectors = m_floppy_expected_sectors->read(); + uint32_t track_zero_expected_sectors = m_floppy_track_zero_expected_sectors->read(); + uint8_t sector = m_fdc->sector_r(); + uint8_t track = m_fdc->track_r(); + + if (track_zero_expected_sectors && track == 0) + { + uint8_t expected_side = sector > track_zero_expected_sectors ? 1 : 0; + + if (m_fdc_side != expected_side) + { + logerror("%s Unexpected size %d for track %d sector %d expected side %d\n", machine().describe_context(), m_fdc_side, track, sector, expected_side); + if (m_fdc_floppy) + { + m_fdc_floppy->ss_w(expected_side); + m_fdc_side = expected_side; + } + } + } + + if (expected_sectors) + { + uint8_t expected_side = sector > expected_sectors ? 1 : 0; + + if (m_fdc_side != expected_side) + { + logerror("%s Unexpected side %d for track %d sector %d expected side %d\n", machine().describe_context(), m_fdc_side, track, sector, expected_side); + if (m_fdc_floppy) + { + m_fdc_floppy->ss_w(expected_side); + m_fdc_side = expected_side; + } + } + } } - else +} + +// Note the dden line is low for double density. +uint8_t swtpc09_state::validate_fdc_dden(uint8_t dden) +{ + uint8_t expected_density = m_floppy_expected_density->read(); + switch (expected_density) { - swtpc09_irq_handler(ACIA_IRQ, CLEAR_LINE); - logerror("swtpc09_acia_irq_clear\n"); + case 1: + // Single density. + if (!dden) + logerror("%s Unexpected DDEN %d for single density\n", machine().describe_context(), dden); + return 1; + case 2: + { + // Double density with track zero single density. + uint8_t track = m_fdc->track_r(); + + if (track == 0) + { + if (!dden) + logerror("%s Unexpected DDEN %d for single density trak 0\n", machine().describe_context(), dden); + return 1; + } + if (dden) + logerror("%s Unexpected DDEN %d for double density\n", machine().describe_context(), dden); + return 0; + } + case 3: + // Pure double density. + if (dden) + logerror("%s Unexpected DDEN %d for double density\n", machine().describe_context(), dden); + return 0; + default: + return dden; } } +// The WD2797 supports an alternate interpretation of the sector size. Check +// that the flag is as expected and return the corrected command if necessary. +uint8_t swtpc09_state::validate_fdc_sector_size(uint8_t cmd) +{ + if ((cmd & 0xe1) == 0x80 || (cmd & 0xe0) == 0xa0) + { + // Check that the sector length flag is set as expected. + uint8_t sector_length_default = cmd & 0x08; + if (sector_length_default != 0x08) + { + logerror("%s Unexpected sector length default %02x\n", machine().describe_context(), sector_length_default); + // Patch the sector length flag. + cmd |= 0x08; + } + } + return cmd; +} + /*********************************************************************/ -/* DMF2 Floppy Controller Board */ +/* DMAF2 Floppy Controller Board */ /*********************************************************************/ -/* DMF2 dma extended address register */ -READ8_MEMBER ( swtpc09_state::dmf2_dma_address_reg_r ) +READ8_MEMBER( swtpc09_state::dmaf2_fdc_r ) +{ + // TODO Does access to the dmaf2 fdc also trigger the motor timer? + if (!machine().side_effects_disabled()) + floppy_motor_trigger(); + return m_fdc->fd1797_device::read(offset); +} + +WRITE8_MEMBER ( swtpc09_state::dmaf2_fdc_w ) +{ + // TODO Does access to the dmaf2 fdc also trigger the motor timer. + floppy_motor_trigger(); + + // TODO how does the DMAF2 use the FDC SSO output? + + if (offset == 0) { + validate_floppy_side(data); + data = validate_fdc_sector_size(data); + } + + m_fdc->fd1797_device::write(offset, data); +} + +/* DMAF2 dma extended address register */ +READ8_MEMBER ( swtpc09_state::dmaf2_dma_address_reg_r ) { return m_fdc_dma_address_reg; } -WRITE8_MEMBER ( swtpc09_state::dmf2_dma_address_reg_w ) +WRITE8_MEMBER ( swtpc09_state::dmaf2_dma_address_reg_w ) { m_fdc_dma_address_reg = data; - // bit 4 controls a gate enable/disable for DMF2 fdc irq line - if ((m_fdc_dma_address_reg & 0x10) && (m_system_type == UNIFLEX_DMF2 || m_system_type == FLEX_DMF2)) + // bit 4 controls a gate enable/disable for DMAF2 fdc irq line + if ((m_fdc_dma_address_reg & 0x10) && (m_system_type == UNIFLEX_DMAF2 || m_system_type == FLEX_DMAF2)) swtpc09_irq_handler(FDC_IRQ, CLEAR_LINE); //then clear the irq to cpu - - logerror("swtpc09_dmf2_dma_address_reg_w %02X\n", data); } -/* DMF2 fdc control register */ -READ8_MEMBER ( swtpc09_state::dmf2_control_reg_r ) +/* DMAF2 fdc control register */ +READ8_MEMBER ( swtpc09_state::dmaf2_control_reg_r ) { - //logerror("swtpc09_dmf2_control_reg_r $%02X\n", m_fdc_status); return m_fdc_status; } -WRITE8_MEMBER ( swtpc09_state::dmf2_control_reg_w ) +WRITE8_MEMBER ( swtpc09_state::dmaf2_control_reg_w ) { - logerror("swtpc09_dmf2_control_reg_w $%02X\n", data); - floppy_image_device *floppy = nullptr; + // TODO what to do if multiple drives are selected? + if (!BIT(data, 0) + !BIT(data, 1) + !BIT(data, 2) + !BIT(data, 3) > 1) + { + logerror("%s Unexpected DMAF2 has multiple drives selected: %d %d %d %d\n", machine().describe_context(), !BIT(data, 0), !BIT(data, 1), !BIT(data, 2), !BIT(data, 3)); + } + if (!BIT(data, 0)) floppy = m_floppy0->get_device(); if (!BIT(data, 1)) floppy = m_floppy1->get_device(); if (!BIT(data, 2)) floppy = m_floppy2->get_device(); if (!BIT(data, 3)) floppy = m_floppy3->get_device(); m_fdc->set_floppy(floppy); + m_fdc_floppy = floppy; if (floppy) { - floppy->mon_w(0); - floppy->ss_w(!BIT(data, 4)); + uint8_t side = !BIT(data, 4); + floppy->ss_w(side); + m_fdc_side = side; } - m_fdc->dden_w(!BIT(data, 5)); + uint8_t dden = !BIT(data, 5); + dden = validate_fdc_dden(dden); + m_fdc->dden_w(dden); } /* FDC controller dma transfer */ @@ -152,7 +302,6 @@ void swtpc09_state::swtpc09_fdc_dma_transfer() { uint8_t data = m_fdc->data_r(); - logerror("swtpc09_dma_write_mem %05X %02X\n", m_m6844_channel[0].address + offset, data); space.write_byte(m_m6844_channel[0].address + offset, data); } else @@ -160,7 +309,6 @@ void swtpc09_state::swtpc09_fdc_dma_transfer() uint8_t data = space.read_byte(m_m6844_channel[0].address + offset); m_fdc->data_w(data); - //logerror("swtpc09_dma_read_mem %04X %02X\n", m_m6844_channel[0].address, data); } m_m6844_channel[0].address++; @@ -182,8 +330,6 @@ void swtpc09_state::swtpc09_fdc_dma_transfer() /* common interrupt handler */ void swtpc09_state::swtpc09_irq_handler(uint8_t peripheral, uint8_t state) { - logerror("swtpc09_irq_handler peripheral:%02X state:%02X\n", peripheral, state); - switch (state) { case ASSERT_LINE: @@ -191,20 +337,18 @@ void swtpc09_state::swtpc09_irq_handler(uint8_t peripheral, uint8_t state) break; case CLEAR_LINE: - m_interrupt &= (~peripheral & 0x3f); + m_interrupt &= (~peripheral & 0x7f); break; } if (!m_active_interrupt && m_interrupt) //no active interrupt and it needs to be asserted { - m_maincpu->set_input_line(INPUT_LINE_IRQ0, ASSERT_LINE); + m_maincpu->set_input_line(M6809_IRQ_LINE, ASSERT_LINE); m_active_interrupt=true; - logerror("swtpc09_irq_assert %02X\n", peripheral); } else if (m_active_interrupt && !m_interrupt) //active interrupt and it needs to be cleared { - m_maincpu->set_input_line(INPUT_LINE_IRQ0, CLEAR_LINE); - logerror("swtpc09_irq_clear %02X\n", peripheral); + m_maincpu->set_input_line(M6809_IRQ_LINE, CLEAR_LINE); m_active_interrupt=false; } } @@ -212,54 +356,40 @@ void swtpc09_state::swtpc09_irq_handler(uint8_t peripheral, uint8_t state) /* handlers for fdc */ WRITE_LINE_MEMBER( swtpc09_state::fdc_intrq_w ) { - logerror("swtpc09_fdc_intrq_w %02X\n", state); - if ( m_system_type == UNIFLEX_DMF3 ) //IRQ from 1791 is connect into VIA ca2 + if ( m_system_type == UNIFLEX_DMAF3 ) //IRQ from 1791 is connect into VIA ca2 { if (state) { m_fdc_status |= 0x40; m_via->write_cb2(0); //fdc interrupt is connected to CA1 - m_dmf3_via_porta &= 0xfb; //clear pa3 - //m_via->write_porta(m_dmf3_via_porta); //and connected to PA3 + m_dmaf3_via_porta &= 0xfb; //clear pa3 + //m_via->write_porta(m_dmaf3_via_porta); //and connected to PA3 //swtpc09_irq_handler(FDC_IRQ, ASSERT_LINE); } else { m_fdc_status &= ~0x40; m_via->write_cb2(1); - m_dmf3_via_porta |= 0x04; //and connected to PA3 - //m_via->write_porta(m_dmf3_via_porta); //and connected to PA3 + m_dmaf3_via_porta |= 0x04; //and connected to PA3 + //m_via->write_porta(m_dmaf3_via_porta); //and connected to PA3 //swtpc09_irq_handler(FDC_IRQ, CLEAR_LINE); } } - else if ( m_system_type == FLEX_DC4_PIAIDE ) //for dc4 emulate irq jumper out + else //for dmaf2 it is connected directly to cpu via a gate { if (state) { m_fdc_status |= 0x40; - } - else - { - m_fdc_status &= ~0x40; - } - } - else //for dmf2 it is connected directly to cpu via a gate - { - if (state) - { - m_fdc_status |= 0x40; - if (!(m_fdc_dma_address_reg & 0x10)) // is dmf2 fdc irq enabled + if (!(m_fdc_dma_address_reg & 0x10)) // is dmaf2 fdc irq enabled { - logerror("swtpc09_fdc_int ** assert\n"); swtpc09_irq_handler(FDC_IRQ, ASSERT_LINE); } } else { m_fdc_status &= ~0x40; - if (!(m_fdc_dma_address_reg & 0x10)) // is dmf2 fdc irq enabled + if (!(m_fdc_dma_address_reg & 0x10)) // is dmaf2 fdc irq enabled { - logerror("swtpc09_fdc_int ** clear\n"); swtpc09_irq_handler(FDC_IRQ, CLEAR_LINE); } } @@ -268,55 +398,69 @@ WRITE_LINE_MEMBER( swtpc09_state::fdc_intrq_w ) WRITE_LINE_MEMBER( swtpc09_state::fdc_drq_w ) { - if (m_system_type == FLEX_DC4_PIAIDE) //for dc4 no dma + if (state) { - if (state) - { - m_fdc_status |= 0x80; - } - else - m_fdc_status &= 0x7f; + m_fdc_status |= 0x80; + swtpc09_fdc_dma_transfer(); } else - { - if (state) - { - m_fdc_status |= 0x80; - swtpc09_fdc_dma_transfer(); - } - else - m_fdc_status &= 0x7f; - } + m_fdc_status &= 0x7f; +} + +WRITE_LINE_MEMBER( swtpc09_state::fdc_sso_w ) +{ + // Doese the DMAF2 or DMAF3 use the SSO output? } /*********************************************************************/ -/* DMF3 Board */ +/* DMAF3 Board */ /*********************************************************************/ -/* via on dmf3 board */ -READ8_MEMBER( swtpc09_state::dmf3_via_read_porta ) +READ8_MEMBER( swtpc09_state::dmaf3_fdc_r ) { - return m_dmf3_via_porta; + // TODO Does access to the fdc also trigger the motor timer. + if (!machine().side_effects_disabled()) + floppy_motor_trigger(); + return m_fdc->fd1797_device::read(offset); +} + +WRITE8_MEMBER ( swtpc09_state::dmaf3_fdc_w ) +{ + // TODO Does access to the fdc also trigger the motor timer. + floppy_motor_trigger(); + + if (offset == 0) { + validate_floppy_side(data); + data = validate_fdc_sector_size(data); + } + + m_fdc->fd1797_device::write(offset, data); } -READ8_MEMBER( swtpc09_state::dmf3_via_read_portb ) +/* via on dmaf3 board */ +READ8_MEMBER( swtpc09_state::dmaf3_via_read_porta ) +{ + return m_dmaf3_via_porta; +} + +READ8_MEMBER( swtpc09_state::dmaf3_via_read_portb ) { return 0xff; } -WRITE8_MEMBER( swtpc09_state::dmf3_via_write_porta ) +WRITE8_MEMBER( swtpc09_state::dmaf3_via_write_porta ) { - m_dmf3_via_porta &= data; + m_dmaf3_via_porta &= data; } -//WRITE_LINE_MEMBER( swtpc09_state::dmf3_via_write_ca1 ) +//WRITE_LINE_MEMBER( swtpc09_state::dmaf3_via_write_ca1 ) //{ // return m_via_ca1_input; -// logerror("swtpc09_dmf3_via_write_ca1 %02X\n", state); +// logerror("swtpc09_dmaf3_via_write_ca1 %02X\n", state); //} -WRITE_LINE_MEMBER( swtpc09_state::dmf3_via_irq ) +WRITE_LINE_MEMBER( swtpc09_state::dmaf3_via_irq ) { if (state) swtpc09_irq_handler(VIA_IRQ, ASSERT_LINE); @@ -324,117 +468,64 @@ WRITE_LINE_MEMBER( swtpc09_state::dmf3_via_irq ) swtpc09_irq_handler(VIA_IRQ, CLEAR_LINE); } -/* DMF3 dma extended address register */ -READ8_MEMBER ( swtpc09_state::dmf3_dma_address_reg_r ) +/* DMAF3 dma extended address register */ +READ8_MEMBER ( swtpc09_state::dmaf3_dma_address_reg_r ) { return m_fdc_dma_address_reg; } -WRITE8_MEMBER ( swtpc09_state::dmf3_dma_address_reg_w ) +WRITE8_MEMBER ( swtpc09_state::dmaf3_dma_address_reg_w ) { m_fdc_dma_address_reg = data; - logerror("swtpc09_dmf3_dma_address_reg_w %02X\n", data); } -/* DMF3 fdc control register */ -READ8_MEMBER ( swtpc09_state::dmf3_control_reg_r ) +/* DMAF3 fdc control register */ +READ8_MEMBER ( swtpc09_state::dmaf3_control_reg_r ) { - //logerror("swtpc09_dmf3_control_reg_r $%02X\n", m_fdc_status); return m_fdc_status; } -WRITE8_MEMBER ( swtpc09_state::dmf3_control_reg_w ) +WRITE8_MEMBER ( swtpc09_state::dmaf3_control_reg_w ) { - logerror("swtpc09_dmf3_control_reg_w $%02X\n", data); - floppy_image_device *floppy = nullptr; - if (BIT(data, 0)) floppy = m_floppy0->get_device(); - if (BIT(data, 1)) floppy = m_floppy1->get_device(); - if (BIT(data, 2)) floppy = m_floppy2->get_device(); - if (BIT(data, 3)) floppy = m_floppy3->get_device(); - - m_fdc->set_floppy(floppy); - - if (floppy) + // TODO multiple selected? + if (BIT(data, 0) + BIT(data, 1) + BIT(data, 2) + BIT(data, 3) > 1) { - floppy->mon_w(0); - floppy->ss_w(BIT(data, 4)); + logerror("%s Unexpected DMAF3 has multiple drives selected: %d %d %d %d\n", machine().describe_context(), !BIT(data, 0), !BIT(data, 1), !BIT(data, 2), !BIT(data, 3)); } - m_fdc->dden_w(BIT(data, 5)); -} - -// DC4 drive select - -WRITE8_MEMBER ( swtpc09_state::dc4_control_reg_w ) -{ - logerror("swtpc09_dc4_control_reg_w $%02X\n", data); - - floppy_image_device *floppy = nullptr; - if (BIT(data, 0)) floppy = m_floppy0->get_device(); if (BIT(data, 1)) floppy = m_floppy1->get_device(); if (BIT(data, 2)) floppy = m_floppy2->get_device(); if (BIT(data, 3)) floppy = m_floppy3->get_device(); m_fdc->set_floppy(floppy); -} - + m_fdc_floppy = floppy; -/******* MC6821 PIA on IDE Board *******/ -/* Read/Write handlers for pia ide */ -/* TODO: update and finish this off */ + if (floppy) + { + uint8_t side = BIT(data, 4); + floppy->ss_w(side); + m_fdc_side = side; + } -READ8_MEMBER( swtpc09_state::piaide_a_r ) -{ - return m_piaide_porta; + uint8_t dden = BIT(data, 5); + dden = validate_fdc_dden(dden); + m_fdc->dden_w(dden); } -READ8_MEMBER( swtpc09_state::piaide_b_r ) -{ - return m_piaide_portb; -} +// DMAF3 WD1000 +// TODO. The following might help: +// http://www.bitsavers.org/pdf/westernDigital/WD100x/WD1000_OEM_Manual.pdf -WRITE8_MEMBER( swtpc09_state::piaide_a_w ) +READ8_MEMBER( swtpc09_state::dmaf3_wd_r ) { - m_piaide_porta = data; + return 0x00; } -WRITE8_MEMBER( swtpc09_state::piaide_b_w ) +WRITE8_MEMBER ( swtpc09_state::dmaf3_wd_w ) { - int tempidedata; - - m_piaide_portb = data; - - if ((data & 0x40)&&(!(data&0x20))) //cs0=0 cs1=1 bit 5&6 - { - if (!(data & 0x02)) //rd line bit 1 - { - tempidedata = m_ide->read_cs0((data&0x1c)>>2); - logerror("swtpc09_ide_bus_r: offset $%02X data %04X\n", (data&0x1c)>>2, tempidedata); - m_piaide_porta = tempidedata & 0x00ff; - } - else if (!(data & 0x01)) //wr line bit 0 - { - m_ide->write_cs0((data&0x1c)>>2, m_piaide_porta); - logerror("swtpc09_ide_bus_w: offset $%02X data %04X\n", (data&0x1c)>>2, m_piaide_porta); - } - } - else if ((data & 0x20)&&(!(data&0x40))) //cs0=1 cs1=0 bit 5&6 - { - if (!(data & 0x02)) //rd line bit 1 - { - tempidedata = m_ide->read_cs1((data&0x1c)>>2); - logerror("swtpc09_ide_bus_r: offset $%02X data %04X\n", (data&0x1c)>>2, tempidedata); - m_piaide_porta = tempidedata & 0x00ff; - } - else if (!(data & 0x01)) //wr line bit 0 - { - m_ide->write_cs1((data&0x1c)>>2, m_piaide_porta); - logerror("swtpc09_ide_bus_w: offset $%02X data %04X\n", (data&0x1c)>>2, m_piaide_porta); - } - } } @@ -451,12 +542,26 @@ offs_t swtpc09_state::dat_translate(offs_t offset) const READ8_MEMBER(swtpc09_state::main_r) { - return m_banked_space->read_byte(dat_translate(offset)); + if (offset < 0xff00) + { + return m_banked_space->read_byte(dat_translate(offset)); + } + else + { + return m_banked_space->read_byte(offset | 0xfff00); + } } WRITE8_MEMBER(swtpc09_state::main_w) { - m_banked_space->write_byte(dat_translate(offset), data); + if (offset < 0xff00) + { + m_banked_space->write_byte(dat_translate(offset), data); + } + else + { + m_banked_space->write_byte(offset | 0xfff00, data); + } } /* MC6844 DMA controller I/O */ @@ -465,7 +570,6 @@ READ8_MEMBER( swtpc09_state::m6844_r ) { uint8_t result = 0; - /* switch off the offset we were given */ switch (offset) { @@ -509,12 +613,14 @@ READ8_MEMBER( swtpc09_state::m6844_r ) result = m_m6844_channel[offset - 0x10].control; /* a read here clears the DMA end flag */ - m_m6844_channel[offset - 0x10].control &= ~0x80; - if (m_m6844_interrupt & 0x80) // if interrupt is active, then clear + if (!machine().side_effects_disabled()) { - swtpc09_irq_handler(0x01, CLEAR_LINE); - m_m6844_interrupt &= 0x7f; // clear interrupt indication bit 7 - logerror("swtpc09_6844_r interrupt cleared \n"); + m_m6844_channel[offset - 0x10].control &= ~0x80; + if (m_m6844_interrupt & 0x80) // if interrupt is active, then clear + { + swtpc09_irq_handler(0x01, CLEAR_LINE); + m_m6844_interrupt &= 0x7f; // clear interrupt indication bit 7 + } } break; @@ -536,9 +642,8 @@ READ8_MEMBER( swtpc09_state::m6844_r ) /* 0x17-0x1f not used */ default: break; } - //logerror("swtpc09_6844_r %02X %02X\n", offset, result & 0xff); - if (m_system_type == UNIFLEX_DMF2 || m_system_type == FLEX_DMF2) // if DMF2 controller data bus is inverted to 6844 + if (m_system_type == UNIFLEX_DMAF2 || m_system_type == FLEX_DMAF2) // if DMAF2 controller data bus is inverted to 6844 { return ~result & 0xff; } @@ -553,10 +658,9 @@ WRITE8_MEMBER( swtpc09_state::m6844_w ) { int i; - if (m_system_type == UNIFLEX_DMF2 || m_system_type == FLEX_DMF2) // if DMF2 controller data bus is inverted to 6844 + if (m_system_type == UNIFLEX_DMAF2 || m_system_type == FLEX_DMAF2) // if DMAF2 controller data bus is inverted to 6844 data = ~data & 0xff; - logerror("swtpc09_6844_w %02X %02X\n", offset, data); /* switch off the offset we were given */ switch (offset) { @@ -612,7 +716,6 @@ WRITE8_MEMBER( swtpc09_state::m6844_w ) { /* mark us active */ m_m6844_channel[i].active = 1; - logerror("swtpc09_dma_channel active %02X\n", i); /* set the DMA busy bit and clear the DMA end bit */ m_m6844_channel[i].control |= 0x40; @@ -639,7 +742,6 @@ WRITE8_MEMBER( swtpc09_state::m6844_w ) /* interrupt control */ case 0x15: m_m6844_interrupt = (m_m6844_interrupt & 0x80) | (data & 0x7f); - logerror("swtpc09_m_m6844_interrupt_w %02X\n", m_m6844_interrupt); break; /* chaining control */ @@ -652,6 +754,51 @@ WRITE8_MEMBER( swtpc09_state::m6844_w ) } } +void swtpc09_state::machine_reset() +{ + uint32_t maincpu_clock = m_maincpu_clock->read(); + m_maincpu->set_clock(maincpu_clock * 4); + + if (m_system_type == FLEX_DMAF2 || + m_system_type == UNIFLEX_DMAF2 || + m_system_type == UNIFLEX_DMAF3) + { + uint32_t fdc_clock = m_fdc_clock->read(); + m_fdc->set_unscaled_clock(fdc_clock); + } + + // Divider select X64 is the default Low baud rate setting. A High + // baud rate setting is also available that selects a X16 divider, so + // gives rate four times as high. Note the schematic appears to have + // mislabeled the this setting. + uint8_t baud_rate_high = m_baud_rate_high->read(); + m_brg->rsa_w(baud_rate_high); + m_brg->rsb_w(1); + + // Note UNIBUG has a smarter boot loader in ROM and will toggle the + // density on failure so this is not necessary for UniFLEX. + if ((m_system_type == FLEX_DMAF2 || + m_system_type == FLEX_DC5_PIAIDE) && + m_sbug_double_density->read()) + { + // Patch the boot ROM to load the boot sector in double density. + uint8_t* sbug = memregion("bankdev")->base(); + sbug[0xffaf8] = 0xfe; // 'D' DMAF2 boot path + sbug[0xffb78] = 0xfe; + sbug[0xffbe1] = 0x8e; // 'U' mini boot path + } + + if (m_system_type == FLEX_DC5_PIAIDE && + m_piaide_flex_boot_cd00->read()) + { + // Patch the PIA-IDE boot rom to use IO1 + uint8_t* rom = memregion("bankdev")->base(); + + // Patch the FLEX entry point. + rom[0xfe979] = 0xcd; + rom[0xfe97a] = 0x00; + } +} void swtpc09_state::machine_start() { @@ -660,6 +807,14 @@ void swtpc09_state::machine_start() m_interrupt = 0; m_active_interrupt = false; + m_fdc_side = 0; + + // Start with the IRQ disabled? + m_fdc_dma_address_reg = 0x10; + + m_floppy_motor_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(swtpc09_state::floppy_motor_callback),this)); + m_floppy_motor_on = 0; + // reset the 6844 for (int i = 0; i < 4; i++) { @@ -671,28 +826,25 @@ void swtpc09_state::machine_start() m_m6844_chain = 0x00; m_banked_space = &subdevice("bankdev")->space(AS_PROGRAM); - - m_brg->rsa_w(0); - m_brg->rsb_w(1); } void swtpc09_state::init_swtpc09() { - m_system_type = FLEX_DMF2; + m_system_type = FLEX_DMAF2; } void swtpc09_state::init_swtpc09i() { - m_system_type = FLEX_DC4_PIAIDE; + m_system_type = FLEX_DC5_PIAIDE; } void swtpc09_state::init_swtpc09u() { - m_system_type = UNIFLEX_DMF2; + m_system_type = UNIFLEX_DMAF2; } void swtpc09_state::init_swtpc09d3() { m_via_ca1_input = 0; - m_system_type = UNIFLEX_DMF3; + m_system_type = UNIFLEX_DMAF3; } -- cgit v1.2.3