swtpc09: add hard disk support for the DMAF3 controller

This uses the WD1000 driver.

The DMAF2/3 6844 DMA support had to be improved to support multiple channels,
and now supports a separate high addresses for each channel. It now also
support addresses increasing or decreasing. These controllers use different
DMA channels for the floppy and the hard disk, and also a tape archiver which
is not yet implemented.

This gets UniFLEX running using a hard disk for storage, and does not appear
to regress the floppy support or other variants using the DMAF2.
This commit is contained in:
68bit 2019-07-31 11:26:04 +10:00
parent ae4a4581bc
commit 27d2ae2cf6
4 changed files with 339 additions and 104 deletions

View File

@ -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);

View File

@ -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));
}

View File

@ -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

View File

@ -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;
// 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));
}
// The DMAF2 data lines are inverted.
data = ~data & 0xff;
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();
// 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)
{
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);
}
}
WRITE8_MEMBER ( swtpc09_state::dmaf3_wd_w )
WRITE_LINE_MEMBER( swtpc09_state::dmaf3_hdc_drq_w )
{
if (state)
m6844_hdc_dma_transfer(1);
}
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);
}