diff options
author | R. Belmont <rb6502@users.noreply.github.com> | 2019-08-21 09:51:27 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-08-21 09:51:27 -0400 |
commit | 05a69c3f1521f5f4f4a420de45461cc90bfe44c4 (patch) | |
tree | 83f06e3d8fff30103a8298f30bf3f5916e1d059b | |
parent | 517e654062bedd3e70048957652ed4d270f74659 (diff) | |
parent | 1c7adc2338dd5618a8381b68adb734508b1e73ad (diff) |
Merge pull request #5519 from 68bit/swtpc09-update
swtpc09: update, use the SS-30 bus, get these working.
-rw-r--r-- | src/mame/drivers/swtpc09.cpp | 526 | ||||
-rw-r--r-- | src/mame/includes/swtpc09.h | 117 | ||||
-rw-r--r-- | 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<ss50_interface_port_device>("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<ss50_interface_port_device>("io1")->set_default_option("dc5"); + subdevice<ss50_interface_port_device>("io1")->set_option_device_input_defaults("dc5", DEVICE_INPUT_DEFAULTS_NAME(dc5)); + subdevice<ss50_interface_port_device>("io4")->set_default_option("mpt"); + subdevice<ss50_interface_port_device>("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<mc6809_device> m_maincpu; required_device<mc14411_device> m_brg; required_device<pia6821_device> m_pia; required_device<ptm6840_device> m_ptm; - required_device<acia6850_device> m_acia; - required_device<fd1793_device> m_fdc; - required_device<floppy_connector> m_floppy0; - required_device<floppy_connector> m_floppy1; - required_device<floppy_connector> m_floppy2; - required_device<floppy_connector> m_floppy3; + + optional_device<fd1797_device> m_fdc; + optional_device<floppy_connector> m_floppy0; + optional_device<floppy_connector> m_floppy1; + optional_device<floppy_connector> m_floppy2; + optional_device<floppy_connector> m_floppy3; + optional_device<via6522_device> m_via; - optional_device<pia6821_device> m_piaide; - optional_device<device_t> m_harddisk; - optional_device<ide_controller_device> m_ide; required_shared_ptr<uint8_t> m_dat; required_device<address_map_bank_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<address_map_bank_device>("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; } |