summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author R. Belmont <rb6502@users.noreply.github.com>2019-08-27 07:46:21 -0400
committer GitHub <noreply@github.com>2019-08-27 07:46:21 -0400
commit3f8ab288dd202f2447607d4630a9b8a4fddb30aa (patch)
treeac5782a559a6aa0478b0fc3f8fa8369f45236bf9
parentd7493d5291ed994900e6e98c9cb668f19bd639b3 (diff)
parent27d2ae2cf6d84e608204583bdf97f711fb0cd80c (diff)
Merge pull request #5557 from 68bit/swtpc09d3-hard-disk
swtpc09: add hard disk support for the DMAF3 controller
-rw-r--r--src/devices/machine/wd1000.cpp4
-rw-r--r--src/mame/drivers/swtpc09.cpp40
-rw-r--r--src/mame/includes/swtpc09.h50
-rw-r--r--src/mame/machine/swtpc09.cpp347
4 files changed, 338 insertions, 103 deletions
diff --git a/src/devices/machine/wd1000.cpp b/src/devices/machine/wd1000.cpp
index ede5021be66..a1d969bf008 100644
--- a/src/devices/machine/wd1000.cpp
+++ b/src/devices/machine/wd1000.cpp
@@ -470,10 +470,7 @@ WRITE8_MEMBER( wd1000_device::write )
// bit 6,5 : sector size (0: 256, 1: 512, 3: 128)
// bit 4,3 : drive select (0,1,2,3)
// bit 2,1,0: head select (0-7)
- uint8_t ecc = BIT(data, 7);
- uint8_t sec_size = (data & 0x60) >> 5;
uint8_t drive = (data & 0x18) >> 3;
- uint8_t head = data & 0x7;
m_sdh = data;
// Update the drive ready flag in the status register which
@@ -564,7 +561,6 @@ void wd1000_device::cmd_restore()
void wd1000_device::cmd_read_sector()
{
hard_disk_file *file = m_drives[drive()].drive->get_hard_disk_file();
- hard_disk_info *info = hard_disk_get_info(file);
uint8_t dma = BIT(m_command, 3);
hard_disk_read(file, get_lbasector(), m_buffer);
diff --git a/src/mame/drivers/swtpc09.cpp b/src/mame/drivers/swtpc09.cpp
index 9760351c7f4..6b7b85ba262 100644
--- a/src/mame/drivers/swtpc09.cpp
+++ b/src/mame/drivers/swtpc09.cpp
@@ -26,7 +26,6 @@
#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"
@@ -49,7 +48,7 @@
F000 - F01F DMAF2 MC6844 DMAC
F020 - F023 DMAF2 WD1791 FDC
F024 - F03F DMAF2 Drive select register
- F040 - F041 DMAF2 DMA Address register
+ F040 - F041 DMAF2 DMA Address register, and interrupt enable, latch.
F800 - FFFF ROM
FFF0 - FFFF DAT RAM (only for writes)
@@ -59,9 +58,17 @@
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
+ F025 - F025 DMAF3 74LS374 latch for 4 extended address lines (bits 0-3), DMA.
+ F030 - F03F DMAF3 HDC WD1000
+ F040 - F04F DMAF3 VIA6522
+ F050 - F050 DMAF3 HDC head load toggle
+ F051 - F051 DMAF3 Winchester software reset
+ F052 - F052 DMAF3 Archive reset
+ F053 - F053 DMAF3 Archive clear
+ F060 - ???? DMAF3 archive DMA preset
+
+ F100 - ???? CDS disk 0 controller
+ F300 - ???? CDS disk 1 controller
***************************************************************************/
@@ -92,10 +99,12 @@ void swtpc09_state::flex_dmaf2_mem(address_map &map)
// 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(0xff040, 0xff040).rw(FUNC(swtpc09_state::dmaf2_dma_address_reg_r), FUNC(swtpc09_state::dmaf2_dma_address_reg_w));
map(0xff800, 0xfffff).rom().region("bankdev", 0xff800);
}
@@ -178,10 +187,12 @@ void swtpc09_state::uniflex_dmaf3_mem(address_map &map)
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(0xff030, 0xff03f).rw(m_hdc, FUNC(wd1000_device::read), FUNC(wd1000_device::write));
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(0xff050, 0xff050).rw(FUNC(swtpc09_state::dmaf3_hdc_control_r), FUNC(swtpc09_state::dmaf3_hdc_control_w));
+ map(0xff051, 0xff051).rw(FUNC(swtpc09_state::dmaf3_hdc_reset_r), FUNC(swtpc09_state::dmaf3_hdc_reset_w));
+ map(0xff052, 0xff052).rw(FUNC(swtpc09_state::dmaf3_archive_reset_r), FUNC(swtpc09_state::dmaf3_archive_reset_w));
+ map(0xff053, 0xff053).rw(FUNC(swtpc09_state::dmaf3_archive_clear_r), FUNC(swtpc09_state::dmaf3_archive_clear_w));
map(0xff800, 0xfffff).rom().region("bankdev", 0xff800);
}
@@ -506,12 +517,25 @@ void swtpc09_state::swtpc09d3(machine_config &config)
m_fdc->drq_wr_callback().set(FUNC(swtpc09_state::fdc_drq_w));
m_fdc->sso_wr_callback().set(FUNC(swtpc09_state::fdc_sso_w));
+ // Hard disk
+ WD1000(config, m_hdc, 5_MHz_XTAL);
+ m_hdc->intrq_wr_callback().set(FUNC(swtpc09_state::dmaf3_hdc_intrq_w));
+ m_hdc->drq_wr_callback().set(FUNC(swtpc09_state::dmaf3_hdc_drq_w));
+ HARDDISK(config, "hdc:0", 0);
+ HARDDISK(config, "hdc:1", 0);
+ HARDDISK(config, "hdc:2", 0);
+ HARDDISK(config, "hdc:3", 0);
+
via6522_device &via(VIA6522(config, "via", 4_MHz_XTAL / 4));
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.writepb_handler().set(FUNC(swtpc09_state::dmaf3_via_write_portb));
//via.ca1_handler().set(FUNC(swtpc09_state::dmaf3_via_write_ca1));
via.irq_handler().set(FUNC(swtpc09_state::dmaf3_via_irq));
+
+ INPUT_MERGER_ALL_HIGH(config, "via_cb2").output_handler().set(m_via, FUNC(via6522_device::write_cb2));
+
}
diff --git a/src/mame/includes/swtpc09.h b/src/mame/includes/swtpc09.h
index 8dc3b9169e7..b3e310c5487 100644
--- a/src/mame/includes/swtpc09.h
+++ b/src/mame/includes/swtpc09.h
@@ -18,7 +18,9 @@
#include "machine/6840ptm.h"
#include "machine/6821pia.h"
#include "machine/6522via.h"
+#include "machine/input_merger.h"
#include "imagedev/harddriv.h"
+#include "machine/wd1000.h"
#include "machine/bankdev.h"
#include "machine/mc14411.h"
@@ -37,7 +39,9 @@ public:
, m_floppy1(*this, "fdc:1")
, m_floppy2(*this, "fdc:2")
, m_floppy3(*this, "fdc:3")
+ , m_hdc(*this, "hdc")
, m_via(*this, "via")
+ , m_via_cb2(*this, "via_cb2")
, m_dat(*this, "dat")
, m_bankdev(*this, "bankdev")
, m_maincpu_clock(*this, "maincpu_clock")
@@ -82,6 +86,7 @@ private:
DECLARE_READ8_MEMBER( dmaf3_via_read_porta );
DECLARE_READ8_MEMBER( dmaf3_via_read_portb );
DECLARE_WRITE8_MEMBER( dmaf3_via_write_porta );
+ DECLARE_WRITE8_MEMBER( dmaf3_via_write_portb );
DECLARE_WRITE_LINE_MEMBER( dmaf3_via_irq );
TIMER_CALLBACK_MEMBER(floppy_motor_callback);
@@ -100,8 +105,16 @@ private:
DECLARE_READ8_MEMBER ( dmaf3_control_reg_r );
DECLARE_WRITE8_MEMBER ( dmaf3_control_reg_w );
- DECLARE_READ8_MEMBER( dmaf3_wd_r );
- DECLARE_WRITE8_MEMBER( dmaf3_wd_w );
+ DECLARE_WRITE_LINE_MEMBER(dmaf3_hdc_intrq_w);
+ DECLARE_WRITE_LINE_MEMBER( dmaf3_hdc_drq_w );
+ DECLARE_READ8_MEMBER( dmaf3_hdc_control_r );
+ DECLARE_WRITE8_MEMBER( dmaf3_hdc_control_w );
+ DECLARE_READ8_MEMBER( dmaf3_hdc_reset_r );
+ DECLARE_WRITE8_MEMBER( dmaf3_hdc_reset_w );
+ DECLARE_READ8_MEMBER( dmaf3_archive_reset_r );
+ DECLARE_WRITE8_MEMBER( dmaf3_archive_reset_w );
+ DECLARE_READ8_MEMBER( dmaf3_archive_clear_r );
+ DECLARE_WRITE8_MEMBER( dmaf3_archive_clear_w );
DECLARE_WRITE8_MEMBER(dat_w);
DECLARE_READ8_MEMBER(main_r);
@@ -122,7 +135,6 @@ private:
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();
@@ -144,7 +156,10 @@ private:
optional_device<floppy_connector> m_floppy2;
optional_device<floppy_connector> m_floppy3;
+ optional_device<wd1000_device> m_hdc;
+
optional_device<via6522_device> m_via;
+ optional_device<input_merger_device> m_via_cb2;
required_shared_ptr<uint8_t> m_dat;
required_device<address_map_bank_device> m_bankdev;
required_ioport m_maincpu_clock;
@@ -158,15 +173,17 @@ private:
uint8_t m_pia_counter; // this is the counter on pia porta
- uint8_t m_fdc_dma_address_reg; // dmaf2 or dmaf3 dma extended address reg
+ uint8_t m_dmaf_high_address[4]; // dmaf2 or dmaf3 dma extended address reg
+ uint8_t m_dmaf2_interrupt_enable;
+
uint8_t m_system_type; // flag to indicate hw and rom combination
uint8_t m_fdc_status; // for floppy controller
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_dmaf3_via_portb;
uint8_t m_active_interrupt;
uint8_t m_interrupt;
@@ -180,6 +197,20 @@ private:
int active;
int address;
int counter;
+ // Channel control register.
+ // bit 0: Read / Write mode
+ // bit 1: Mode control B
+ // bit 2: Mode control A
+ // bit 3: Address up (0) / down (1).
+ // bit 4: Not used
+ // bit 5: Not used
+ // bit 6: Busy / Ready. Read only. Set when request
+ // made. Cleared when transfer completed.
+ // bit 7: DMA end flag. Read only? Set when transfer
+ // completed. Cleared when control register
+ // read. Sets IRQ.
+ // Mode control A,B: 0,0 Mode2; 0,1 Mode 3; 1,0 Mode 0;
+ // 1,1 Undefined.
uint8_t control;
int start_address;
int start_counter;
@@ -188,8 +219,17 @@ private:
/* 6844 description */
m6844_channel_data m_m6844_channel[4];
uint8_t m_m6844_priority;
+ // Interrupt control register.
+ // Bit 0-3: channel interrupt enable, 1 enabled, 0 masked.
+ // Bit 4-6: unused
+ // Bit 7: Read only. Set to 1 when IRQ asserted. Clear when the
+ // control register associated with the channel that caused the
+ // interrut is read.
uint8_t m_m6844_interrupt;
uint8_t m_m6844_chain;
+ void m6844_update_interrupt();
+ void m6844_fdc_dma_transfer(uint8_t channel);
+ void m6844_hdc_dma_transfer(uint8_t channel);
};
#endif // MAME_INCLUDES_SWTPC09_H
diff --git a/src/mame/machine/swtpc09.cpp b/src/mame/machine/swtpc09.cpp
index bbf8c34e9d2..ad84096fc79 100644
--- a/src/mame/machine/swtpc09.cpp
+++ b/src/mame/machine/swtpc09.cpp
@@ -227,8 +227,6 @@ 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);
@@ -237,24 +235,37 @@ WRITE8_MEMBER ( swtpc09_state::dmaf2_fdc_w )
m_fdc->fd1797_device::write(offset, data);
}
-/* DMAF2 dma extended address register */
+/* DMAF2 dma extended address register latch. */
+
READ8_MEMBER ( swtpc09_state::dmaf2_dma_address_reg_r )
{
- return m_fdc_dma_address_reg;
+ // This does not appear to be readable.
+ logerror("%s Unexpected read of DMAF2 DMA address reg\n", machine().describe_context());
+ return 0x00;
}
WRITE8_MEMBER ( swtpc09_state::dmaf2_dma_address_reg_w )
{
- m_fdc_dma_address_reg = data;
+ // This latch appears to be write-only, there is no reader function.
+ // The DMAF2 has a single latch for the high address bits, so it would
+ // appear to apply for all DMA channels. These outputs are inverted
+ // which cancels the inversion of the data lines.
+ m_dmaf_high_address[0] = data & 0x0f;
+ m_dmaf_high_address[1] = data & 0x0f;
+ m_dmaf_high_address[2] = data & 0x0f;
+ m_dmaf_high_address[3] = data & 0x0f;
// 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))
+ m_dmaf2_interrupt_enable = !BIT(data, 4);
+ if (!m_dmaf2_interrupt_enable)
swtpc09_irq_handler(FDC_IRQ, CLEAR_LINE); //then clear the irq to cpu
}
/* DMAF2 fdc control register */
READ8_MEMBER ( swtpc09_state::dmaf2_control_reg_r )
{
+ // TODO is this readable?
+ logerror("%s Unexpected read from DMAF2 control reg\n", machine().describe_context());
return m_fdc_status;
}
@@ -262,71 +273,33 @@ WRITE8_MEMBER ( swtpc09_state::dmaf2_control_reg_w )
{
floppy_image_device *floppy = nullptr;
+ // The DMAF2 data lines are inverted.
+ data = ~data & 0xff;
+
// 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) + 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();
+ 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)
{
- uint8_t side = !BIT(data, 4);
+ uint8_t side = BIT(data, 4);
floppy->ss_w(side);
m_fdc_side = side;
}
- uint8_t dden = !BIT(data, 5);
+ uint8_t dden = BIT(data, 5);
dden = validate_fdc_dden(dden);
m_fdc->dden_w(dden);
}
-/* FDC controller dma transfer */
-void swtpc09_state::swtpc09_fdc_dma_transfer()
-{
- uint32_t offset;
- address_space &space = *m_banked_space;
-
- offset = (m_fdc_dma_address_reg & 0x0f)<<16;
-
- if (m_m6844_channel[0].active == 1) //active dma transfer
- {
- if (!(m_m6844_channel[0].control & 0x01)) // dma write to memory
- {
- uint8_t data = m_fdc->data_r();
-
- space.write_byte(m_m6844_channel[0].address + offset, data);
- }
- else
- {
- uint8_t data = space.read_byte(m_m6844_channel[0].address + offset);
-
- m_fdc->data_w(data);
- }
-
- m_m6844_channel[0].address++;
- m_m6844_channel[0].counter--;
-
- if (m_m6844_channel[0].counter == 0) // dma transfer has finished
- {
- m_m6844_channel[0].control |= 0x80; // set dend flag
- if (m_m6844_interrupt & 0x01) // interrupt for channel 0 is enabled?
- {
- m_m6844_interrupt |= 0x80; // set bit 7 to indicate active interrupt
- swtpc09_irq_handler(DMAC_IRQ, ASSERT_LINE);
- }
- }
- }
-
-}
-
/* common interrupt handler */
void swtpc09_state::swtpc09_irq_handler(uint8_t peripheral, uint8_t state)
{
@@ -356,22 +329,26 @@ void swtpc09_state::swtpc09_irq_handler(uint8_t peripheral, uint8_t state)
/* handlers for fdc */
WRITE_LINE_MEMBER( swtpc09_state::fdc_intrq_w )
{
- if ( m_system_type == UNIFLEX_DMAF3 ) //IRQ from 1791 is connect into VIA ca2
+ if ( m_system_type == UNIFLEX_DMAF3 )
{
+ // IRQ from 1791 is connected into VIA CB2 inverted, and
+ // connected to VIA port B bit 2 without inversion.
if (state)
{
m_fdc_status |= 0x40;
- m_via->write_cb2(0); //fdc interrupt is connected to CA1
- m_dmaf3_via_porta &= 0xfb; //clear pa3
- //m_via->write_porta(m_dmaf3_via_porta); //and connected to PA3
+ //m_via->write_cb2(0);
+ m_via_cb2->in_w<0>(0);
+ m_dmaf3_via_portb |= 0x04;
+ //m_via->write_portb(m_dmaf3_via_portb);
//swtpc09_irq_handler(FDC_IRQ, ASSERT_LINE);
}
else
{
m_fdc_status &= ~0x40;
- m_via->write_cb2(1);
- m_dmaf3_via_porta |= 0x04; //and connected to PA3
- //m_via->write_porta(m_dmaf3_via_porta); //and connected to PA3
+ //m_via->write_cb2(1);
+ m_via_cb2->in_w<0>(1);
+ m_dmaf3_via_portb &= 0xfb;
+ //m_via->write_portb(m_dmaf3_via_portb);
//swtpc09_irq_handler(FDC_IRQ, CLEAR_LINE);
}
}
@@ -380,7 +357,7 @@ WRITE_LINE_MEMBER( swtpc09_state::fdc_intrq_w )
if (state)
{
m_fdc_status |= 0x40;
- if (!(m_fdc_dma_address_reg & 0x10)) // is dmaf2 fdc irq enabled
+ if (m_dmaf2_interrupt_enable)
{
swtpc09_irq_handler(FDC_IRQ, ASSERT_LINE);
}
@@ -388,7 +365,7 @@ WRITE_LINE_MEMBER( swtpc09_state::fdc_intrq_w )
else
{
m_fdc_status &= ~0x40;
- if (!(m_fdc_dma_address_reg & 0x10)) // is dmaf2 fdc irq enabled
+ if (m_dmaf2_interrupt_enable)
{
swtpc09_irq_handler(FDC_IRQ, CLEAR_LINE);
}
@@ -401,7 +378,9 @@ WRITE_LINE_MEMBER( swtpc09_state::fdc_drq_w )
if (state)
{
m_fdc_status |= 0x80;
- swtpc09_fdc_dma_transfer();
+ // The DMAF2 schematic shows an input to two pins on the 6844,
+ // it might also trigger channel 1.
+ m6844_fdc_dma_transfer(0);
}
else
m_fdc_status &= 0x7f;
@@ -409,7 +388,7 @@ WRITE_LINE_MEMBER( swtpc09_state::fdc_drq_w )
WRITE_LINE_MEMBER( swtpc09_state::fdc_sso_w )
{
- // Doese the DMAF2 or DMAF3 use the SSO output?
+ // The DMAF2 and DMAF3 do not appear to use a SSO output?
}
/*********************************************************************/
@@ -445,7 +424,18 @@ READ8_MEMBER( swtpc09_state::dmaf3_via_read_porta )
READ8_MEMBER( swtpc09_state::dmaf3_via_read_portb )
{
- return 0xff;
+ // Bit 0 - output ?
+ // Bit 1 - output, tape drive request strobe.
+ // Bit 2 - input, WD1791 FDC interrupt.
+ // Bit 3 - input ?
+ // Bit 4 - input, tape drive ready
+ // Bit 5 - input, tape drive exception, timer 2.
+ // Bit 6 - input ?
+ // Bit 7 - output, UniFLEX configures a timer to toggle this output.
+
+ // Set the tape drive exception bit to avoid detection, otherwise
+ // UniFLEX gets stuck in a loop trying to open the archive driver.
+ return m_dmaf3_via_portb | 0x20;
}
WRITE8_MEMBER( swtpc09_state::dmaf3_via_write_porta )
@@ -453,6 +443,11 @@ WRITE8_MEMBER( swtpc09_state::dmaf3_via_write_porta )
m_dmaf3_via_porta &= data;
}
+WRITE8_MEMBER( swtpc09_state::dmaf3_via_write_portb )
+{
+ m_dmaf3_via_portb &= data;
+}
+
//WRITE_LINE_MEMBER( swtpc09_state::dmaf3_via_write_ca1 )
//{
// return m_via_ca1_input;
@@ -471,17 +466,28 @@ WRITE_LINE_MEMBER( swtpc09_state::dmaf3_via_irq )
/* DMAF3 dma extended address register */
READ8_MEMBER ( swtpc09_state::dmaf3_dma_address_reg_r )
{
- return m_fdc_dma_address_reg;
+ // TODO is this readable?
+ logerror("%s Unexpected read of DMAF3 DMA address reg\n", machine().describe_context());
+ return 0x00;
}
WRITE8_MEMBER ( swtpc09_state::dmaf3_dma_address_reg_w )
{
- m_fdc_dma_address_reg = data;
+ // Based on source code comments it appears that there are four high
+ // address latches, one for each DMA channel. TODO check hardware or a
+ // schematic.
+ uint8_t channel = (data & 0x30) >> 4;
+ m_dmaf_high_address[channel] = data & 0x0f;
+
+ // Bit 6 controls the 'archive edge select'.
+ // Bit 7 controls the DMA halt versus bus-req mode.
}
/* DMAF3 fdc control register */
READ8_MEMBER ( swtpc09_state::dmaf3_control_reg_r )
{
+ // TODO is this readable?
+ logerror("%s Unexpected read from DMAF3 control reg\n", machine().describe_context());
return m_fdc_status;
}
@@ -491,9 +497,7 @@ WRITE8_MEMBER ( swtpc09_state::dmaf3_control_reg_w )
// TODO multiple selected?
if (BIT(data, 0) + BIT(data, 1) + BIT(data, 2) + BIT(data, 3) > 1)
- {
- 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));
- }
+ 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));
if (BIT(data, 0)) floppy = m_floppy0->get_device();
if (BIT(data, 1)) floppy = m_floppy1->get_device();
@@ -515,17 +519,74 @@ WRITE8_MEMBER ( swtpc09_state::dmaf3_control_reg_w )
m_fdc->dden_w(dden);
}
-// DMAF3 WD1000
-// TODO. The following might help:
-// http://www.bitsavers.org/pdf/westernDigital/WD100x/WD1000_OEM_Manual.pdf
+// DMAF3 WD1000 hard disk controller.
-READ8_MEMBER( swtpc09_state::dmaf3_wd_r )
+WRITE_LINE_MEMBER( swtpc09_state::dmaf3_hdc_intrq_w )
{
- return 0x00;
+ // The IRQ from WD1000 is connected into VIA CB2 inverted, and perhaps
+ // connected to a VIA port B bit 3?
+ if (state)
+ {
+ m_via_cb2->in_w<1>(0);
+ //m_dmaf3_via_portb &= 0xf7;
+ //m_via->write_portb(m_dmaf3_via_portb);
+ }
+ else
+ {
+ m_via_cb2->in_w<1>(1);
+ //m_dmaf3_via_portb |= 0x08;
+ //m_via->write_portb(m_dmaf3_via_portb);
+ }
+}
+
+WRITE_LINE_MEMBER( swtpc09_state::dmaf3_hdc_drq_w )
+{
+ if (state)
+ m6844_hdc_dma_transfer(1);
}
-WRITE8_MEMBER ( swtpc09_state::dmaf3_wd_w )
+READ8_MEMBER( swtpc09_state::dmaf3_hdc_control_r )
{
+ // TODO head load toggle?
+ return 0;
+}
+
+WRITE8_MEMBER ( swtpc09_state::dmaf3_hdc_control_w )
+{
+ // TODO head load toggle?
+}
+
+READ8_MEMBER( swtpc09_state::dmaf3_hdc_reset_r )
+{
+ // TODO reset?
+ return 0;
+}
+
+WRITE8_MEMBER ( swtpc09_state::dmaf3_hdc_reset_w )
+{
+ // TODO reset
+}
+
+READ8_MEMBER( swtpc09_state::dmaf3_archive_reset_r )
+{
+ // TODO
+ return 0;
+}
+
+WRITE8_MEMBER ( swtpc09_state::dmaf3_archive_reset_w )
+{
+ // TODO
+}
+
+READ8_MEMBER( swtpc09_state::dmaf3_archive_clear_r )
+{
+ // TODO
+ return 0;
+}
+
+WRITE8_MEMBER ( swtpc09_state::dmaf3_archive_clear_w )
+{
+ // TODO
}
@@ -566,6 +627,110 @@ WRITE8_MEMBER(swtpc09_state::main_w)
/* MC6844 DMA controller I/O */
+
+void swtpc09_state::m6844_update_interrupt()
+{
+ uint8_t interrupt = 0;
+
+ interrupt |= BIT(m_m6844_channel[0].control, 7) & BIT(m_m6844_interrupt, 0);
+ interrupt |= BIT(m_m6844_channel[1].control, 7) & BIT(m_m6844_interrupt, 1);
+ interrupt |= BIT(m_m6844_channel[2].control, 7) & BIT(m_m6844_interrupt, 2);
+ interrupt |= BIT(m_m6844_channel[3].control, 7) & BIT(m_m6844_interrupt, 3);
+
+ if (interrupt)
+ {
+ if (!(m_m6844_interrupt & 0x80))
+ {
+ // Set interrupt indication bit 7.
+ m_m6844_interrupt |= 0x80;
+ swtpc09_irq_handler(DMAC_IRQ, ASSERT_LINE);
+ }
+ }
+ else
+ {
+ if (m_m6844_interrupt & 0x80)
+ {
+ // Clear interrupt indication bit 7.
+ m_m6844_interrupt &= 0x7f;
+ swtpc09_irq_handler(DMAC_IRQ, CLEAR_LINE);
+ }
+ }
+}
+
+void swtpc09_state::m6844_fdc_dma_transfer(uint8_t channel)
+{
+ uint32_t offset;
+ address_space &space = *m_banked_space;
+
+ offset = m_dmaf_high_address[channel] << 16;
+
+ if (m_m6844_channel[channel].active == 1) //active dma transfer
+ {
+ if (!(m_m6844_channel[channel].control & 0x01)) // dma write to memory
+ {
+ uint8_t data = m_fdc->data_r();
+
+ space.write_byte(m_m6844_channel[channel].address + offset, data);
+ }
+ else
+ {
+ uint8_t data = space.read_byte(m_m6844_channel[channel].address + offset);
+
+ m_fdc->data_w(data);
+ }
+
+ if (m_m6844_channel[channel].control & 0x08)
+ m_m6844_channel[channel].address--;
+ else
+ m_m6844_channel[channel].address++;
+
+ m_m6844_channel[channel].counter--;
+
+ if (m_m6844_channel[channel].counter == 0) // dma transfer has finished
+ {
+ m_m6844_channel[channel].control |= 0x80; // set dend flag
+ m6844_update_interrupt();
+ }
+ }
+}
+
+void swtpc09_state::m6844_hdc_dma_transfer(uint8_t channel)
+{
+ uint32_t offset;
+ address_space &space = *m_banked_space;
+
+ offset = m_dmaf_high_address[channel] << 16;
+
+ if (m_m6844_channel[channel].active == 1) //active dma transfer
+ {
+ if (!(m_m6844_channel[channel].control & 0x01)) // dma write to memory
+ {
+ uint8_t data = m_hdc->data_r();
+
+ space.write_byte(m_m6844_channel[channel].address + offset, data);
+ }
+ else
+ {
+ uint8_t data = space.read_byte(m_m6844_channel[channel].address + offset);
+
+ m_hdc->data_w(data);
+ }
+
+ if (m_m6844_channel[channel].control & 0x08)
+ m_m6844_channel[channel].address--;
+ else
+ m_m6844_channel[channel].address++;
+
+ m_m6844_channel[channel].counter--;
+
+ if (m_m6844_channel[channel].counter == 0) // dma transfer has finished
+ {
+ m_m6844_channel[channel].control |= 0x80; // set dend flag
+ m6844_update_interrupt();
+ }
+ }
+}
+
READ8_MEMBER( swtpc09_state::m6844_r )
{
uint8_t result = 0;
@@ -612,15 +777,13 @@ READ8_MEMBER( swtpc09_state::m6844_r )
case 0x13:
result = m_m6844_channel[offset - 0x10].control;
- /* a read here clears the DMA end flag */
+ // A read here clears the 'DMA end' flag of the
+ // associated channel.
if (!machine().side_effects_disabled())
{
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
- }
+ if (m_m6844_interrupt & 0x80)
+ m6844_update_interrupt();
}
break;
@@ -742,6 +905,7 @@ WRITE8_MEMBER( swtpc09_state::m6844_w )
/* interrupt control */
case 0x15:
m_m6844_interrupt = (m_m6844_interrupt & 0x80) | (data & 0x7f);
+ m6844_update_interrupt();
break;
/* chaining control */
@@ -775,6 +939,11 @@ void swtpc09_state::machine_reset()
m_brg->rsa_w(baud_rate_high);
m_brg->rsb_w(1);
+ m_pia->write_portb(0);
+ m_pia->cb1_w(0);
+ m_pia->ca2_w(0);
+ m_pia->cb2_w(0);
+
// 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 ||
@@ -810,7 +979,12 @@ void swtpc09_state::machine_start()
m_fdc_side = 0;
// Start with the IRQ disabled?
- m_fdc_dma_address_reg = 0x10;
+ m_dmaf2_interrupt_enable = 0;
+
+ m_dmaf_high_address[0] = 0;
+ m_dmaf_high_address[1] = 0;
+ m_dmaf_high_address[2] = 0;
+ m_dmaf_high_address[3] = 0;
m_floppy_motor_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(swtpc09_state::floppy_motor_callback),this));
m_floppy_motor_on = 0;
@@ -845,6 +1019,7 @@ void swtpc09_state::init_swtpc09u()
void swtpc09_state::init_swtpc09d3()
{
- m_via_ca1_input = 0;
m_system_type = UNIFLEX_DMAF3;
+ // UniFLEX numbers sectors from 1.
+ m_hdc->set_sector_base(1);
}