summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Olivier Galibert <galibert@pobox.com>2022-12-19 11:47:08 +0100
committer Olivier Galibert <galibert@pobox.com>2023-02-22 11:29:48 +0100
commit82814d3b50831a1d9a67ca26a317b31a76bb904e (patch)
tree0ab536e84354438071ce99cc1561ace527543699
parentaebf6eddd883acd3ee43e177e33055af03624e7e (diff)
atarist: Extract the MMU, will need STE memory map specialization
-rw-r--r--src/devices/cpu/m68000/m68000.cpp2
-rw-r--r--src/mame/atari/atarist.cpp585
-rw-r--r--src/mame/atari/stmmu.cpp501
-rw-r--r--src/mame/atari/stmmu.h105
4 files changed, 672 insertions, 521 deletions
diff --git a/src/devices/cpu/m68000/m68000.cpp b/src/devices/cpu/m68000/m68000.cpp
index df7b00a4c63..e3a9b5fc8ff 100644
--- a/src/devices/cpu/m68000/m68000.cpp
+++ b/src/devices/cpu/m68000/m68000.cpp
@@ -301,7 +301,7 @@ void m68000_device::device_reset()
void m68000_device::update_user_super()
{
- if(m_sr & 0x2000) {
+ if(m_sr & SR_S) {
m_sp = 16;
m_program = m_r_program;
m_opcodes = m_r_opcodes;
diff --git a/src/mame/atari/atarist.cpp b/src/mame/atari/atarist.cpp
index e19c7b00b15..bf361d2f88d 100644
--- a/src/mame/atari/atarist.cpp
+++ b/src/mame/atari/atarist.cpp
@@ -5,6 +5,7 @@
#include "ataristb.h"
#include "atarist_v.h"
#include "stkbd.h"
+#include "stmmu.h"
#include "bus/centronics/ctronics.h"
#include "bus/generic/slot.h"
@@ -93,21 +94,6 @@ namespace {
#define Y200 XTAL(2'457'600)
#define Y700 XTAL(10'000'000)
-#define DMA_STATUS_DRQ 0x04
-#define DMA_STATUS_SECTOR_COUNT 0x02
-#define DMA_STATUS_ERROR 0x01
-
-#define DMA_MODE_READ_WRITE 0x100
-#define DMA_MODE_FDC_HDC_ACK 0x080
-#define DMA_MODE_ENABLED 0x040
-#define DMA_MODE_SECTOR_COUNT 0x010
-#define DMA_MODE_FDC_HDC_CS 0x008
-#define DMA_MODE_A1 0x004
-#define DMA_MODE_A0 0x002
-#define DMA_MODE_ADDRESS_MASK 0x006
-
-#define DMA_SECTOR_SIZE 512
-
static const double DMASOUND_RATE[] = { Y2/640.0/8.0, Y2/640.0/4.0, Y2/640.0/2.0, Y2/640.0 };
class st_state : public driver_device
@@ -116,7 +102,9 @@ public:
st_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag),
m_maincpu(*this, M68000_TAG),
+ m_mainram(*this, "mainram", 0x400000, ENDIANNESS_BIG),
m_ikbd(*this, "ikbd"),
+ m_mmu(*this, "mmu"),
m_stb(*this, "stb"),
m_fdc(*this, WD1772_TAG),
m_floppy(*this, WD1772_TAG ":%u", 0U),
@@ -124,7 +112,7 @@ public:
m_acia(*this, {MC6850_0_TAG, MC6850_1_TAG}),
m_centronics(*this, CENTRONICS_TAG),
m_cart(*this, "cartslot"),
- m_ram(*this, RAM_TAG),
+ m_ramcfg(*this, RAM_TAG),
m_rs232(*this, RS232_TAG),
m_ymsnd(*this, YM2149_TAG),
m_config(*this, "config"),
@@ -139,7 +127,9 @@ public:
protected:
required_device<m68000_device> m_maincpu;
+ memory_share_creator<u16> m_mainram;
required_device<st_kbd_device> m_ikbd;
+ required_device<st_mmu_device> m_mmu;
optional_device<st_blitter_device> m_stb;
required_device<wd1772_device> m_fdc;
required_device_array<floppy_connector, 2> m_floppy;
@@ -147,55 +137,17 @@ protected:
required_device_array<acia6850_device, 2> m_acia;
required_device<centronics_device> m_centronics;
required_device<generic_slot_device> m_cart;
- required_device<ram_device> m_ram;
+ required_device<ram_device> m_ramcfg;
required_device<rs232_port_device> m_rs232;
required_device<ym2149_device> m_ymsnd;
optional_ioport m_config;
TIMER_CALLBACK_MEMBER(mouse_tick);
- // driver
- uint16_t fdc_data_r(offs_t offset);
- void fdc_data_w(offs_t offset, uint16_t data);
- uint16_t dma_status_r();
- void dma_mode_w(uint16_t data);
- uint8_t dma_counter_r(offs_t offset);
- void dma_base_w(offs_t offset, uint8_t data);
- uint8_t mmu_r();
- void mmu_w(uint8_t data);
-
- DECLARE_WRITE_LINE_MEMBER( fdc_drq_w );
-
void psg_pa_w(uint8_t data);
DECLARE_WRITE_LINE_MEMBER( reset_w );
- void toggle_dma_fifo();
- void flush_dma_fifo();
- void fill_dma_fifo();
- void fdc_dma_transfer();
-
- void configure_memory();
- void state_save();
-
- /* memory state */
- uint8_t m_mmu = 0U;
-
- /* floppy state */
- uint32_t m_dma_base = 0U;
- uint16_t m_dma_error = 0U;
- uint16_t m_fdc_mode = 0U;
- uint8_t m_fdc_sectors = 0U;
- uint16_t m_fdc_fifo[2][8]{};
- int m_fdc_fifo_sel = 0;
- int m_fdc_fifo_index = 0;
- int m_fdc_fifo_msb = 0;
- int m_fdc_fifo_empty[2]{};
- int m_fdc_dmabytes = 0;
-
- /* timers */
- emu_timer *m_mouse_timer = nullptr;
-
static void floppy_formats(format_registration &fr);
int m_monochrome;
@@ -204,8 +156,9 @@ protected:
void common(machine_config &config);
void cpu_space_map(address_map &map);
- void st_map(address_map &map);
- void megast_map(address_map &map);
+ void st_super_map(address_map &map);
+ void st_user_map(address_map &map);
+ void megast_super_map(address_map &map);
uint16_t fpu_r();
void fpu_w(uint16_t data);
@@ -280,7 +233,7 @@ public:
void tt030(machine_config &config);
void falcon(machine_config &config);
void ste(machine_config &config);
- void ste_map(address_map &map);
+ void ste_super_map(address_map &map);
protected:
virtual void machine_start() override;
};
@@ -297,7 +250,7 @@ public:
uint16_t m_cache = 0;
void megaste(machine_config &config);
- void megaste_map(address_map &map);
+ void megaste_super_map(address_map &map);
protected:
virtual void machine_start() override;
@@ -325,365 +278,6 @@ protected:
//**************************************************************************
-// FLOPPY
-//**************************************************************************
-
-//-------------------------------------------------
-// toggle_dma_fifo -
-//-------------------------------------------------
-
-void st_state::toggle_dma_fifo()
-{
- if (LOG) logerror("Toggling DMA FIFO\n");
-
- m_fdc_fifo_sel = !m_fdc_fifo_sel;
- m_fdc_fifo_index = 0;
-}
-
-
-//-------------------------------------------------
-// flush_dma_fifo -
-//-------------------------------------------------
-
-void st_state::flush_dma_fifo()
-{
- if (m_fdc_fifo_empty[m_fdc_fifo_sel]) return;
-
- if (m_fdc_dmabytes)
- {
- address_space &program = m_maincpu->space(AS_PROGRAM);
- for (int i = 0; i < 8; i++)
- {
- uint16_t data = m_fdc_fifo[m_fdc_fifo_sel][i];
-
- if (LOG) logerror("Flushing DMA FIFO %u data %04x to address %06x\n", m_fdc_fifo_sel, data, m_dma_base);
-
- if (m_dma_base >= 8)
- program.write_word(m_dma_base, data);
- m_dma_base += 2;
- }
- m_fdc_dmabytes -= 16;
- if (!m_fdc_dmabytes)
- {
- m_fdc_sectors--;
-
- if (m_fdc_sectors)
- m_fdc_dmabytes = DMA_SECTOR_SIZE;
- }
- }
- else
- m_dma_error = 0;
-
- m_fdc_fifo_empty[m_fdc_fifo_sel] = 1;
-}
-
-
-//-------------------------------------------------
-// fill_dma_fifo -
-//-------------------------------------------------
-
-void st_state::fill_dma_fifo()
-{
- if (m_fdc_dmabytes)
- {
- address_space &program = m_maincpu->space(AS_PROGRAM);
- for (int i = 0; i < 8; i++)
- {
- uint16_t data = program.read_word(m_dma_base);
-
- if (LOG) logerror("Filling DMA FIFO %u with data %04x from memory address %06x\n", m_fdc_fifo_sel, data, m_dma_base);
-
- m_fdc_fifo[m_fdc_fifo_sel][i] = data;
- m_dma_base += 2;
- }
- m_fdc_dmabytes -= 16;
- if (!m_fdc_dmabytes)
- {
- m_fdc_sectors--;
-
- if (m_fdc_sectors)
- m_fdc_dmabytes = DMA_SECTOR_SIZE;
- }
- }
- else
- m_dma_error = 0;
-
- m_fdc_fifo_empty[m_fdc_fifo_sel] = 0;
-}
-
-
-//-------------------------------------------------
-// fdc_dma_transfer -
-//-------------------------------------------------
-
-void st_state::fdc_dma_transfer()
-{
- if (m_fdc_mode & DMA_MODE_READ_WRITE)
- {
- uint16_t data = m_fdc_fifo[m_fdc_fifo_sel][m_fdc_fifo_index];
-
- if (m_fdc_fifo_msb)
- {
- // write LSB to disk
- m_fdc->data_w(data & 0xff);
-
- if (LOG) logerror("DMA Write to FDC %02x\n", data & 0xff);
-
- m_fdc_fifo_index++;
- }
- else
- {
- // write MSB to disk
- m_fdc->data_w(data >> 8);
-
- if (LOG) logerror("DMA Write to FDC %02x\n", data >> 8);
- }
-
- // toggle MSB/LSB
- m_fdc_fifo_msb = !m_fdc_fifo_msb;
-
- if (m_fdc_fifo_index == 8)
- {
- m_fdc_fifo_index--;
- m_fdc_fifo_empty[m_fdc_fifo_sel] = 1;
-
- toggle_dma_fifo();
-
- if (m_fdc_fifo_empty[m_fdc_fifo_sel])
- {
- fill_dma_fifo();
- }
- }
- }
- else
- {
- // read from controller to FIFO
- uint8_t data = m_fdc->data_r();
-
- m_fdc_fifo_empty[m_fdc_fifo_sel] = 0;
-
- if (LOG) logerror("DMA Read from FDC %02x\n", data);
-
- if (m_fdc_fifo_msb)
- {
- // write MSB to FIFO
- m_fdc_fifo[m_fdc_fifo_sel][m_fdc_fifo_index] |= data;
- m_fdc_fifo_index++;
- }
- else
- {
- // write LSB to FIFO
- m_fdc_fifo[m_fdc_fifo_sel][m_fdc_fifo_index] = data << 8;
- }
-
- // toggle MSB/LSB
- m_fdc_fifo_msb = !m_fdc_fifo_msb;
-
- if (m_fdc_fifo_index == 8)
- {
- flush_dma_fifo();
- toggle_dma_fifo();
- }
- }
-}
-
-
-//-------------------------------------------------
-// fdc_data_r -
-//-------------------------------------------------
-
-uint16_t st_state::fdc_data_r(offs_t offset)
-{
- uint8_t data = 0;
-
- if (m_fdc_mode & DMA_MODE_SECTOR_COUNT)
- {
- if (LOG) logerror("Indeterminate DMA Sector Count Read!\n");
-
- // sector count register is write only, reading it returns unpredictable values
- data = machine().rand() & 0xff;
- }
- else
- {
- if (!(m_fdc_mode & DMA_MODE_FDC_HDC_CS))
- {
- // floppy controller
- offs_t offset = (m_fdc_mode & DMA_MODE_ADDRESS_MASK) >> 1;
-
- data = m_fdc->read(offset);
-
- if (LOG) logerror("FDC Register %u Read %02x\n", offset, data);
- }
- }
-
- return data;
-}
-
-
-//-------------------------------------------------
-// fdc_data_w -
-//-------------------------------------------------
-
-void st_state::fdc_data_w(offs_t offset, uint16_t data)
-{
- if (m_fdc_mode & DMA_MODE_SECTOR_COUNT)
- {
- if (LOG) logerror("DMA Sector Count %u\n", data);
-
- // sector count register
- m_fdc_sectors = data;
-
- if (m_fdc_sectors)
- {
- m_fdc_dmabytes = DMA_SECTOR_SIZE;
- }
-
- if (m_fdc_mode & DMA_MODE_READ_WRITE)
- {
- // fill both FIFOs with data
- fill_dma_fifo();
- toggle_dma_fifo();
- fill_dma_fifo();
- toggle_dma_fifo();
- }
- }
- else
- {
- if (!(m_fdc_mode & DMA_MODE_FDC_HDC_CS))
- {
- // floppy controller
- offs_t offset = (m_fdc_mode & DMA_MODE_ADDRESS_MASK) >> 1;
-
- if (LOG) logerror("FDC Register %u Write %02x\n", offset, data);
-
- m_fdc->write(offset, data);
- }
- }
-}
-
-
-//-------------------------------------------------
-// dma_status_r -
-//-------------------------------------------------
-
-uint16_t st_state::dma_status_r()
-{
- uint16_t data = 0;
-
- // DMA error
- data |= m_dma_error;
-
- // sector count null
- data |= !(m_fdc_sectors == 0) << 1;
-
- // DRQ state
- data |= m_fdc->drq_r() << 2;
-
- return data;
-}
-
-
-//-------------------------------------------------
-// dma_mode_w -
-//-------------------------------------------------
-
-void st_state::dma_mode_w(uint16_t data)
-{
- if (LOG) logerror("DMA Mode %04x\n", data);
-
- if ((data & DMA_MODE_READ_WRITE) != (m_fdc_mode & DMA_MODE_READ_WRITE))
- {
- if (LOG) logerror("DMA reset\n");
-
- m_dma_error = 1;
- m_fdc_sectors = 0;
- m_fdc_fifo_sel = 0;
- m_fdc_fifo_msb = 0;
- m_fdc_fifo_index = 0;
- }
-
- m_fdc_mode = data;
-}
-
-
-//-------------------------------------------------
-// dma_counter_r -
-//-------------------------------------------------
-
-uint8_t st_state::dma_counter_r(offs_t offset)
-{
- uint8_t data = 0;
-
- switch (offset)
- {
- case 0:
- data = (m_dma_base >> 16) & 0xff;
- break;
- case 1:
- data = (m_dma_base >> 8) & 0xff;
- break;
- case 2:
- data = m_dma_base & 0xff;
- break;
- }
-
- return data;
-}
-
-
-//-------------------------------------------------
-// dma_base_w -
-//-------------------------------------------------
-
-void st_state::dma_base_w(offs_t offset, uint8_t data)
-{
- switch (offset)
- {
- case 0:
- m_dma_base = (m_dma_base & 0x00ffff) | (data << 16);
- if (LOG) logerror("DMA Address High %02x (%06x)\n", data & 0xff, m_dma_base);
- break;
-
- case 1:
- m_dma_base = (m_dma_base & 0xff00ff) | (data << 8);
- if (LOG) logerror("DMA Address Mid %02x (%06x)\n", data & 0xff, m_dma_base);
- break;
-
- case 2:
- m_dma_base = (m_dma_base & 0xffff00) | data;
- if (LOG) logerror("DMA Address Low %02x (%06x)\n", data & 0xff, m_dma_base);
- break;
- }
-}
-
-
-
-//**************************************************************************
-// MMU
-//**************************************************************************
-
-//-------------------------------------------------
-// mmu_r -
-//-------------------------------------------------
-
-uint8_t st_state::mmu_r()
-{
- return m_mmu;
-}
-
-
-//-------------------------------------------------
-// mmu_w -
-//-------------------------------------------------
-
-void st_state::mmu_w(uint8_t data)
-{
- if (LOG) logerror("Memory Configuration Register: %02x\n", data);
-
- m_mmu = data;
-}
-
-//**************************************************************************
// FPU
//**************************************************************************
@@ -762,11 +356,9 @@ TIMER_CALLBACK_MEMBER(ste_state::dmasound_tick)
{
if (m_dmasnd_samples == 0)
{
- uint8_t *RAM = m_ram->pointer();
-
for (auto & elem : m_dmasnd_fifo)
{
- elem = RAM[m_dmasnd_cntr];
+ elem = m_mainram[m_dmasnd_cntr];
m_dmasnd_cntr++;
m_dmasnd_samples++;
@@ -1198,55 +790,61 @@ void st_state::cpu_space_map(address_map &map)
// ADDRESS_MAP( st_map )
//-------------------------------------------------
-void st_state::st_map(address_map &map)
+void st_state::st_super_map(address_map &map)
{
+ // Ram mapped by the mmu
map.unmap_value_high();
map(0x000000, 0x000007).rom().region(M68000_TAG, 0).w(m_maincpu, FUNC(m68000_device::berr_w));
- map(0x000008, 0x1fffff).ram();
- map(0x200000, 0x3fffff).ram();
map(0x400000, 0xf9ffff).rw(m_maincpu, FUNC(m68000_device::berr_r), FUNC(m68000_device::berr_w));
//map(0xfa0000, 0xfbffff) // mapped by the cartslot
map(0xfc0000, 0xfeffff).rom().region(M68000_TAG, 0).w(m_maincpu, FUNC(m68000_device::berr_w));
- map(0xff8001, 0xff8001).rw(FUNC(st_state::mmu_r), FUNC(st_state::mmu_w));
+ map(0xff8000, 0xff8fff).m(m_mmu, FUNC(st_mmu_device::map));
+
map(0xff8200, 0xff8203).rw(m_video, FUNC(st_video_device::shifter_base_r), FUNC(st_video_device::shifter_base_w)).umask16(0x00ff);
map(0xff8204, 0xff8209).r(m_video, FUNC(st_video_device::shifter_counter_r)).umask16(0x00ff);
map(0xff820a, 0xff820a).rw(m_video, FUNC(st_video_device::shifter_sync_r), FUNC(st_video_device::shifter_sync_w));
map(0xff8240, 0xff825f).rw(m_video, FUNC(st_video_device::shifter_palette_r), FUNC(st_video_device::shifter_palette_w));
map(0xff8260, 0xff8260).rw(m_video, FUNC(st_video_device::shifter_mode_r), FUNC(st_video_device::shifter_mode_w));
- map(0xff8604, 0xff8605).rw(FUNC(st_state::fdc_data_r), FUNC(st_state::fdc_data_w));
- map(0xff8606, 0xff8607).rw(FUNC(st_state::dma_status_r), FUNC(st_state::dma_mode_w));
- map(0xff8608, 0xff860d).rw(FUNC(st_state::dma_counter_r), FUNC(st_state::dma_base_w)).umask16(0x00ff);
+
map(0xff8800, 0xff8800).rw(YM2149_TAG, FUNC(ay8910_device::data_r), FUNC(ay8910_device::address_w)).mirror(0xfc);
map(0xff8802, 0xff8802).rw(YM2149_TAG, FUNC(ay8910_device::data_r), FUNC(ay8910_device::data_w)).mirror(0xfc);
+
// no blitter on original ST
+
map(0xfffa00, 0xfffa3f).rw(m_mfp, FUNC(mc68901_device::read), FUNC(mc68901_device::write)).umask16(0x00ff);
map(0xfffc00, 0xfffc03).rw(m_acia[0], FUNC(acia6850_device::read), FUNC(acia6850_device::write)).umask16(0xff00);
map(0xfffc04, 0xfffc07).rw(m_acia[1], FUNC(acia6850_device::read), FUNC(acia6850_device::write)).umask16(0xff00);
}
+void st_state::st_user_map(address_map &map)
+{
+ // Ram mapped by the mmu
+ map.unmap_value_high();
+ map(0x000000, 0x0007ff).rw(m_maincpu, FUNC(m68000_device::berr_r), FUNC(m68000_device::berr_w));
+ map(0x400000, 0xfbffff).rw(m_maincpu, FUNC(m68000_device::berr_r), FUNC(m68000_device::berr_w));
+ map(0xfc0000, 0xfeffff).rom().region(M68000_TAG, 0).w(m_maincpu, FUNC(m68000_device::berr_w));
+ map(0xff0000, 0xffffff).rw(m_maincpu, FUNC(m68000_device::berr_r), FUNC(m68000_device::berr_w));
+}
+
//-------------------------------------------------
// ADDRESS_MAP( megast_map )
//-------------------------------------------------
-void st_state::megast_map(address_map &map)
+void st_state::megast_super_map(address_map &map)
{
map.unmap_value_high();
+ map(0x000000, 0x3fffff).ram().share(m_mainram);
map(0x000000, 0x000007).rom().region(M68000_TAG, 0);
- map(0x000008, 0x1fffff).ram();
- map(0x200000, 0x3fffff).ram();
//map(0xfa0000, 0xfbffff) // mapped by the cartslot
map(0xfc0000, 0xfeffff).rom().region(M68000_TAG, 0);
// map(0xff7f30, 0xff7f31).rw(m_stb, FUNC(st_blitter_device::dst_inc_y_r), FUNC(st_blitter_device::dst_inc_y_w) // for TOS 1.02
- map(0xff8001, 0xff8001).rw(FUNC(st_state::mmu_r), FUNC(st_state::mmu_w));
+ map(0xff8000, 0xff8fff).m(m_mmu, FUNC(st_mmu_device::map));
map(0xff8200, 0xff8203).rw(m_video, FUNC(st_video_device::shifter_base_r), FUNC(st_video_device::shifter_base_w)).umask16(0x00ff);
map(0xff8204, 0xff8209).r(m_video, FUNC(st_video_device::shifter_counter_r)).umask16(0x00ff);
map(0xff820a, 0xff820a).rw(m_video, FUNC(st_video_device::shifter_sync_r), FUNC(st_video_device::shifter_sync_w));
map(0xff8240, 0xff825f).rw(m_video, FUNC(st_video_device::shifter_palette_r), FUNC(st_video_device::shifter_palette_w));
map(0xff8260, 0xff8260).rw(m_video, FUNC(st_video_device::shifter_mode_r), FUNC(st_video_device::shifter_mode_w));
- map(0xff8604, 0xff8605).rw(FUNC(st_state::fdc_data_r), FUNC(st_state::fdc_data_w));
- map(0xff8606, 0xff8607).rw(FUNC(st_state::dma_status_r), FUNC(st_state::dma_mode_w));
- map(0xff8608, 0xff860d).rw(FUNC(st_state::dma_counter_r), FUNC(st_state::dma_base_w)).umask16(0x00ff);
map(0xff8800, 0xff8800).rw(YM2149_TAG, FUNC(ay8910_device::data_r), FUNC(ay8910_device::address_w));
map(0xff8802, 0xff8802).w(YM2149_TAG, FUNC(ay8910_device::data_w));
map(0xff8a00, 0xff8a1f).rw(m_stb, FUNC(st_blitter_device::halftone_r), FUNC(st_blitter_device::halftone_w));
@@ -1273,9 +871,9 @@ void st_state::megast_map(address_map &map)
// ADDRESS_MAP( ste_map )
//-------------------------------------------------
-void ste_state::ste_map(address_map &map)
+void ste_state::ste_super_map(address_map &map)
{
- st_map(map);
+ st_super_map(map);
map(0xe00000, 0xe3ffff).rom().region(M68000_TAG, 0);
map(0xff8901, 0xff8901).rw(FUNC(ste_state::sound_dma_control_r), FUNC(ste_state::sound_dma_control_w));
map(0xff8902, 0xff8907).rw(FUNC(ste_state::sound_dma_base_r), FUNC(ste_state::sound_dma_base_w)).umask16(0x00ff);
@@ -1311,9 +909,9 @@ void ste_state::ste_map(address_map &map)
// ADDRESS_MAP( megaste_map )
//-------------------------------------------------
-void megaste_state::megaste_map(address_map &map)
+void megaste_state::megaste_super_map(address_map &map)
{
- megast_map(map);
+ megast_super_map(map);
map(0xe00000, 0xe3ffff).rom().region(M68000_TAG, 0);
map(0xff8c80, 0xff8c87).rw(Z8530_TAG, FUNC(scc8530_legacy_device::reg_r), FUNC(scc8530_legacy_device::reg_w)).umask16(0x00ff);
map(0xff8901, 0xff8901).rw(FUNC(megaste_state::sound_dma_control_r), FUNC(megaste_state::sound_dma_control_w));
@@ -1332,8 +930,7 @@ void megaste_state::megaste_map(address_map &map)
#if 0
void stbook_state::stbook_map(address_map &map)
{
- map(0x000000, 0x1fffff).ram();
- map(0x200000, 0x3fffff).ram();
+ map(0x000000, 0x3fffff).ram().share(m_mainram);
// map(0xd40000, 0xd7ffff).rom();
map(0xe00000, 0xe3ffff).rom().region(M68000_TAG, 0);
// map(0xe80000, 0xebffff).rom();
@@ -1586,76 +1183,21 @@ void stbook_state::psg_pa_w(uint8_t data)
m_fdc->dden_w(BIT(data, 7));
}
-WRITE_LINE_MEMBER( st_state::fdc_drq_w )
-{
- if (state && (!(m_fdc_mode & DMA_MODE_ENABLED)) && (m_fdc_mode & DMA_MODE_FDC_HDC_ACK))
- fdc_dma_transfer();
-}
-
-
//**************************************************************************
// MACHINE INITIALIZATION
//**************************************************************************
//-------------------------------------------------
-// configure_memory -
-//-------------------------------------------------
-
-void st_state::configure_memory()
-{
- address_space &program = m_maincpu->space(AS_PROGRAM);
-
- switch (m_ram->size())
- {
- case 256 * 1024:
- program.unmap_readwrite(0x040000, 0x3fffff);
- break;
-
- case 512 * 1024:
- program.unmap_readwrite(0x080000, 0x3fffff);
- break;
-
- case 1024 * 1024:
- program.unmap_readwrite(0x100000, 0x3fffff);
- break;
-
- case 2048 * 1024:
- program.unmap_readwrite(0x200000, 0x3fffff);
- break;
- }
-}
-
-//-------------------------------------------------
-// state_save -
-//-------------------------------------------------
-
-void st_state::state_save()
-{
- m_dma_error = 1;
-
- save_item(NAME(m_mmu));
- save_item(NAME(m_dma_base));
- save_item(NAME(m_dma_error));
- save_item(NAME(m_fdc_mode));
- save_item(NAME(m_fdc_sectors));
- save_item(NAME(m_fdc_dmabytes));
-}
-
-//-------------------------------------------------
// MACHINE_START( st )
//-------------------------------------------------
void st_state::machine_start()
{
- // configure RAM banking
- configure_memory();
+ m_mmu->set_ram_size(m_ramcfg->size());
if (m_cart->exists())
m_maincpu->space(AS_PROGRAM).install_read_handler(0xfa0000, 0xfbffff, read16s_delegate(*m_cart, FUNC(generic_slot_device::read16_rom)));
- // register for state saving
- state_save();
-
/// TODO: get callbacks to trigger these.
m_mfp->i0_w(1);
m_mfp->i4_w(1);
@@ -1670,8 +1212,6 @@ void st_state::machine_start()
void ste_state::state_save()
{
- st_state::state_save();
-
save_item(NAME(m_dmasnd_base));
save_item(NAME(m_dmasnd_end));
save_item(NAME(m_dmasnd_cntr));
@@ -1694,8 +1234,7 @@ void ste_state::state_save()
void ste_state::machine_start()
{
- /* configure RAM banking */
- configure_memory();
+ m_mmu->set_ram_size(m_ramcfg->size());
if (m_cart->exists())
m_maincpu->space(AS_PROGRAM).install_read_handler(0xfa0000, 0xfbffff, read16s_delegate(*m_cart, FUNC(generic_slot_device::read16_rom)));
@@ -1733,10 +1272,10 @@ void megaste_state::machine_start()
void stbook_state::machine_start()
{
- /* configure RAM banking */
+ /* configure RAM size */
address_space &program = m_maincpu->space(AS_PROGRAM);
- switch (m_ram->size())
+ switch (m_ramcfg->size())
{
case 1024 * 1024:
program.unmap_readwrite(0x100000, 0x3fffff);
@@ -1780,8 +1319,14 @@ void st_state::common(machine_config &config)
// basic machine hardware
M68000(config, m_maincpu, Y2/4);
m_maincpu->set_addrmap(m68000_base_device::AS_CPU_SPACE, &st_state::cpu_space_map);
+ m_maincpu->set_addrmap(m68000_base_device::AS_USER_PROGRAM, &st_state::st_user_map);
m_maincpu->reset_cb().set(FUNC(st_state::reset_w));
+ ST_MMU(config, m_mmu);
+ m_mmu->set_ram(m_mainram);
+ m_mmu->set_cpu(m_maincpu);
+ m_mmu->set_fdc(m_fdc);
+
// sound
YM2149(config, m_ymsnd, Y2/16);
m_ymsnd->set_flags(AY8910_SINGLE_OUTPUT);
@@ -1792,7 +1337,7 @@ void st_state::common(machine_config &config)
// devices
WD1772(config, m_fdc, Y2/4);
m_fdc->intrq_wr_callback().set(m_mfp, FUNC(mc68901_device::i5_w)).invert();
- m_fdc->drq_wr_callback().set(FUNC(st_state::fdc_drq_w));
+ m_fdc->drq_wr_callback().set(m_mmu, FUNC(st_mmu_device::fdc_drq_w));
FLOPPY_CONNECTOR(config, WD1772_TAG ":0", atari_floppies, "35dd", st_state::floppy_formats);
FLOPPY_CONNECTOR(config, WD1772_TAG ":1", atari_floppies, nullptr, st_state::floppy_formats);
@@ -1861,7 +1406,7 @@ void st_state::st(machine_config &config)
common(config);
// basic machine hardware
- m_maincpu->set_addrmap(AS_PROGRAM, &st_state::st_map);
+ m_maincpu->set_addrmap(AS_PROGRAM, &st_state::st_super_map);
// video hardware
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
@@ -1878,9 +1423,9 @@ void st_state::st(machine_config &config)
m_ymsnd->add_route(ALL_OUTPUTS, "mono", 1.00);
// internal ram
- RAM(config, m_ram);
- m_ram->set_default_size("1M"); // 1040ST
- m_ram->set_extra_options("512K,256K"); // 520ST, 260ST
+ RAM(config, m_ramcfg);
+ m_ramcfg->set_default_size("1M"); // 1040ST
+ m_ramcfg->set_extra_options("512K,256K"); // 520ST, 260ST
}
@@ -1893,7 +1438,7 @@ void megast_state::megast(machine_config &config)
common(config);
// basic machine hardware
- m_maincpu->set_addrmap(AS_PROGRAM, &megast_state::megast_map);
+ m_maincpu->set_addrmap(AS_PROGRAM, &megast_state::megast_super_map);
ST_BLITTER(config, m_stb, Y2/4);
m_stb->set_space(m_maincpu, AS_PROGRAM);
@@ -1917,9 +1462,9 @@ void megast_state::megast(machine_config &config)
RP5C15(config, RP5C15_TAG, XTAL(32'768));
// internal ram
- RAM(config, m_ram);
- m_ram->set_default_size("4M"); // Mega ST 4
- m_ram->set_extra_options("2M,1M"); // Mega ST 2, Mega ST 1
+ RAM(config, m_ramcfg);
+ m_ramcfg->set_default_size("4M"); // Mega ST 4
+ m_ramcfg->set_extra_options("2M,1M"); // Mega ST 2, Mega ST 1
}
@@ -1932,7 +1477,7 @@ void ste_state::ste(machine_config &config)
common(config);
// basic machine hardware
- m_maincpu->set_addrmap(AS_PROGRAM, &ste_state::ste_map);
+ m_maincpu->set_addrmap(AS_PROGRAM, &ste_state::ste_super_map);
ST_BLITTER(config, m_stb, Y2/4);
m_stb->set_space(m_maincpu, AS_PROGRAM);
@@ -1961,9 +1506,9 @@ void ste_state::ste(machine_config &config)
LMC1992(config, LMC1992_TAG);
// internal ram
- RAM(config, m_ram);
- m_ram->set_default_size("1M"); // 1040STe
- m_ram->set_extra_options("512K"); // 520STe
+ RAM(config, m_ramcfg);
+ m_ramcfg->set_default_size("1M"); // 1040STe
+ m_ramcfg->set_extra_options("512K"); // 520STe
}
@@ -1974,13 +1519,13 @@ void ste_state::ste(machine_config &config)
void megaste_state::megaste(machine_config &config)
{
ste(config);
- m_maincpu->set_addrmap(AS_PROGRAM, &megaste_state::megaste_map);
+ m_maincpu->set_addrmap(AS_PROGRAM, &megaste_state::megaste_super_map);
RP5C15(config, RP5C15_TAG, XTAL(32'768));
SCC8530(config, Z8530_TAG, Y2/4);
/* internal ram */
- m_ram->set_default_size("4M"); // Mega STe 4
- m_ram->set_extra_options("2M,1M"); // Mega STe 2, Mega STe 1
+ m_ramcfg->set_default_size("4M"); // Mega STe 4
+ m_ramcfg->set_extra_options("2M,1M"); // Mega STe 2, Mega STe 1
}
@@ -2081,7 +1626,7 @@ void stbook_state::stbook(machine_config &config)
SOFTWARE_LIST(config, "cart_list").set_original("st_cart");
/* internal ram */
- RAM(config, m_ram).set_default_size("4M").set_extra_options("1M");
+ RAM(config, m_ramcfg).set_default_size("4M").set_extra_options("1M");
}
#endif
diff --git a/src/mame/atari/stmmu.cpp b/src/mame/atari/stmmu.cpp
new file mode 100644
index 00000000000..bb92ae5658a
--- /dev/null
+++ b/src/mame/atari/stmmu.cpp
@@ -0,0 +1,501 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder, Olivier Galibert
+
+#include "emu.h"
+#include "stmmu.h"
+
+#define LOG_MODE (1U << 1) // Shows mode
+#define LOG_PORT (1U << 2) // Shows direct data read/write
+#define LOG_DMA (1U << 3) // Shows dma address and sector count setup
+#define LOG_DATA (1U << 4) // Shows dma-ed data
+#define LOG_RAM (1U << 5) // Shows ram configuration
+
+#define VERBOSE (LOG_RAM)
+
+//#define VERBOSE (LOG_DESC | LOG_COMMAND | LOG_MATCH | LOG_WRITE | LOG_STATE | LOG_LINES | LOG_COMP | LOG_CRC )
+//#define LOG_OUTPUT_STREAM std::cout
+
+#include "logmacro.h"
+
+#define LOGMODE(...) LOGMASKED(LOG_MODE, __VA_ARGS__)
+#define LOGPORT(...) LOGMASKED(LOG_PORT, __VA_ARGS__)
+#define LOGDMA(...) LOGMASKED(LOG_DMA, __VA_ARGS__)
+#define LOGDATA(...) LOGMASKED(LOG_DATA, __VA_ARGS__)
+#define LOGRAM(...) LOGMASKED(LOG_RAM, __VA_ARGS__)
+
+
+DEFINE_DEVICE_TYPE(ST_MMU, st_mmu_device, "st_mmu", "Atari ST MMU")
+
+void st_mmu_device::map(address_map &map)
+{
+ map(0x001, 0x001).rw(FUNC(st_mmu_device::memcfg_r), FUNC(st_mmu_device::memcfg_w));
+ map(0x604, 0x605).rw(FUNC(st_mmu_device::data_r), FUNC(st_mmu_device::data_w));
+ map(0x606, 0x607).rw(FUNC(st_mmu_device::dma_status_r), FUNC(st_mmu_device::dma_mode_w));
+ map(0x609, 0x609).rw(FUNC(st_mmu_device::dma_address_h_r), FUNC(st_mmu_device::dma_address_h_w));
+ map(0x60b, 0x60b).rw(FUNC(st_mmu_device::dma_address_m_r), FUNC(st_mmu_device::dma_address_m_w));
+ map(0x60d, 0x60d).rw(FUNC(st_mmu_device::dma_address_l_r), FUNC(st_mmu_device::dma_address_l_w));
+}
+
+st_mmu_device::st_mmu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, ST_MMU, tag, owner, clock),
+ m_ram(*this, finder_base::DUMMY_TAG),
+ m_cpu(*this, finder_base::DUMMY_TAG),
+ m_fdc(*this, finder_base::DUMMY_TAG)
+{
+ m_ram_size = 0;
+}
+
+void st_mmu_device::device_start()
+{
+ save_item(NAME(m_ram_size));
+ save_item(NAME(m_dma_address));
+ save_item(NAME(m_dma_mode));
+ save_item(NAME(m_fifo));
+ save_item(NAME(m_block_count));
+ save_item(NAME(m_sector_count));
+ save_item(NAME(m_fifo_index));
+ save_item(NAME(m_memcfg));
+ save_item(NAME(m_fdc_drq));
+ save_item(NAME(m_hdc_drq));
+ save_item(NAME(m_dma_no_error));
+}
+
+void st_mmu_device::device_reset()
+{
+ m_dma_address = 0;
+ m_dma_mode = 0;
+ memset(m_fifo, 0, sizeof(m_fifo));
+ m_sector_count = 0;
+ m_block_count = 0;
+ m_fifo_index = 0;
+ m_memcfg = 0;
+ m_fdc_drq = false;
+ m_hdc_drq = false;
+ m_dma_no_error = true;
+ configure_ram();
+}
+
+void st_mmu_device::fdc_transfer()
+{
+ if(m_dma_mode & MODE_READ_WRITE)
+ m_fdc->data_w(fifo_pop());
+ else
+ fifo_push(m_fdc->data_r());
+}
+
+void st_mmu_device::hdc_transfer()
+{
+ logerror("hdc transfer unimplemented\n");
+}
+
+void st_mmu_device::fdc_drq_w(int state)
+{
+ if(state == m_fdc_drq)
+ return;
+ m_fdc_drq = state;
+ while(m_fdc_drq && (m_dma_mode & MODE_FDC_HDC_ACK))
+ fdc_transfer();
+}
+
+void st_mmu_device::hdc_drq_w(int state)
+{
+ if(state == m_hdc_drq)
+ return;
+ m_hdc_drq = state;
+ while(m_hdc_drq && !(m_dma_mode & MODE_FDC_HDC_ACK))
+ hdc_transfer();
+}
+
+uint16_t st_mmu_device::data_r()
+{
+ if(m_dma_mode & MODE_SECTOR_COUNT)
+ // Sector count is not readable
+ return 0x55;
+
+ else if(m_dma_mode & MODE_FDC_HDC_CS) {
+ u8 r = 0x00;
+ LOGPORT("hdc_r %02x\n", r);
+ return 0;
+
+ } else {
+ u8 r = m_fdc->read((m_dma_mode >> 1) & 3);
+ LOGPORT("fdc_r %02x\n", r);
+ return r;
+ }
+}
+
+void st_mmu_device::data_w(uint16_t data)
+{
+ data &= 0xff;
+ if(m_dma_mode & MODE_SECTOR_COUNT) {
+ LOGDMA("sector_count_w %02x\n", data);
+ m_sector_count = data;
+ if(data == 0)
+ m_dma_no_error = false;
+ else if(m_dma_mode & MODE_READ_WRITE)
+ fifo_schedule_block_transfer_from_ram();
+
+ } else if(m_dma_mode & MODE_FDC_HDC_CS) {
+ LOGPORT("hdc_w %02x\n", data);
+
+ } else {
+ LOGPORT("fdc_w %d, %02x\n", (m_dma_mode >> 1) & 3, data);
+ m_fdc->write((m_dma_mode >> 1) & 3, data);
+ }
+}
+
+uint16_t st_mmu_device::dma_status_r()
+{
+ return (m_dma_no_error ? 1 : 0) | (m_sector_count ? 2 : 0) | (m_fdc_drq ? 4 : 0);
+}
+
+void st_mmu_device::dma_mode_w(uint16_t data)
+{
+ if((m_dma_mode ^ data) & MODE_READ_WRITE)
+ fifo_flush();
+
+ m_dma_mode = data;
+ LOGMODE("mode %04x %c%c%c%c%c%d\n", m_dma_mode,
+ m_dma_mode & MODE_READ_WRITE ? 'w' : 'r',
+ m_dma_mode & MODE_FDC_HDC_ACK ? 'f' : 'h',
+ m_dma_mode & MODE_ENABLED ? '+' : '-',
+ m_dma_mode & MODE_SECTOR_COUNT ? 'C' : '.',
+ m_dma_mode & MODE_FDC_HDC_CS ? 'h' : 'f',
+ (m_dma_mode >> 1) & 3);
+
+ while(m_fdc_drq && (m_dma_mode & MODE_FDC_HDC_ACK))
+ fdc_transfer();
+ while(m_hdc_drq && !(m_dma_mode & MODE_FDC_HDC_ACK))
+ hdc_transfer();
+}
+
+uint8_t st_mmu_device::dma_address_h_r()
+{
+ return m_dma_address >> 16;
+}
+
+uint8_t st_mmu_device::dma_address_m_r()
+{
+ return m_dma_address >> 8;
+}
+
+uint8_t st_mmu_device::dma_address_l_r()
+{
+ return m_dma_address;
+}
+
+void st_mmu_device::dma_address_h_w(uint8_t data)
+{
+ m_dma_address = (m_dma_address & 0x00ffff) | (data << 16);
+ LOGDMA("dma address %06x\n", m_dma_address);
+}
+
+void st_mmu_device::dma_address_m_w(uint8_t data)
+{
+ m_dma_address = (m_dma_address & 0xff00ff) | (data << 8);
+}
+
+void st_mmu_device::dma_address_l_w(uint8_t data)
+{
+ m_dma_address = (m_dma_address & 0xffff00) | data;
+}
+
+
+void st_mmu_device::fifo_flush()
+{
+ m_fifo_index = 0;
+ m_sector_count = 0;
+ m_block_count = 0;
+ m_dma_no_error = true;
+}
+
+void st_mmu_device::fifo_push(u8 data)
+{
+ if(m_fifo_index == 32 || !m_sector_count) {
+ m_dma_no_error = false;
+ return;
+ }
+
+ int idx = m_fifo_index >> 1;
+ if(m_fifo_index & 1)
+ m_fifo[idx] = data | (m_fifo[idx] & 0xff00);
+ else
+ m_fifo[idx] = (data << 8) | (m_fifo[idx] & 0x00ff);
+ m_fifo_index ++;
+ if(m_fifo_index == 16)
+ fifo_schedule_block_transfer_to_ram();
+}
+
+u8 st_mmu_device::fifo_pop()
+{
+ if(m_fifo_index == 32) {
+ m_dma_no_error = false;
+ return 0x00;
+ }
+
+ int idx = m_fifo_index >> 1;
+ u8 r;
+ if(m_fifo_index & 1)
+ r = m_fifo[idx];
+ else
+ r = m_fifo[idx] >> 8;
+ m_fifo_index ++;
+ if(m_fifo_index == 16)
+ fifo_schedule_block_transfer_from_ram();
+ return r;
+}
+
+void st_mmu_device::fifo_schedule_block_transfer_to_ram()
+{
+ if(VERBOSE & LOG_DATA) {
+ std::string l = util::string_format("r %06x =", m_dma_address);
+ for(int i = 0; i != 8; i++)
+ l += util::string_format(" %04x", m_fifo[i]);
+ logerror("%s\n", l);
+ }
+
+ // Synchronous for now
+ for(int i=0; i != 8; i++) {
+ m_ram[(m_dma_address & 0x3ffffe) >> 1] = m_fifo[i];
+ m_dma_address += 2;
+ }
+ memcpy(m_fifo, m_fifo + 8, 8*2);
+ m_fifo_index -= 16;
+ m_block_count ++;
+ if(m_block_count == 32) {
+ m_block_count = 0;
+ m_sector_count --;
+ }
+}
+
+
+void st_mmu_device::fifo_schedule_block_transfer_from_ram()
+{
+ if(!m_sector_count)
+ return;
+
+ // Synchronous for now
+ if(m_fifo_index == 0) {
+ int limit = m_sector_count > 1 || m_block_count != 31 ? 16 : 8;
+ for(int i=0; i != limit; i++) {
+ m_fifo[i] = m_ram[(m_dma_address & 0x3ffffe) >> 1];
+ m_dma_address += 2;
+ }
+ m_block_count += limit == 16 ? 2 : 1;
+ if(VERBOSE & LOG_DATA) {
+ std::string l = util::string_format("w %06x =", m_dma_address-2*limit);
+ for(int i = 0; i != 8; i++)
+ l += util::string_format(" %04x", m_fifo[i]);
+ logerror("%s\n", l);
+ if(limit == 16) {
+ std::string l = util::string_format("w %06x =", m_dma_address-16);
+ for(int i = 0; i != 8; i++)
+ l += util::string_format(" %04x", m_fifo[i+8]);
+ logerror("%s\n", l);
+ }
+ }
+ } else {
+ memcpy(m_fifo, m_fifo + 8, 8*2);
+ for(int i=0; i != 8; i++) {
+ m_fifo[8 + i] = m_ram[(m_dma_address & 0x3ffffe) >> 1];
+ m_dma_address += 2;
+ }
+ m_block_count ++;
+ m_fifo_index -= 16;
+ if(VERBOSE & LOG_DATA) {
+ std::string l = util::string_format("w %06x =", m_dma_address-16);
+ for(int i = 0; i != 8; i++)
+ l += util::string_format(" %04x", m_fifo[i+8]);
+ logerror("%s\n", l);
+ }
+ }
+
+ if(m_block_count == 32) {
+ m_block_count = 0;
+ m_sector_count --;
+ }
+}
+
+
+uint8_t st_mmu_device::memcfg_r()
+{
+ return m_memcfg;
+}
+
+void st_mmu_device::memcfg_w(uint8_t data)
+{
+ m_memcfg = data;
+ configure_ram();
+}
+
+void st_mmu_device::set_ram_size(u32 size)
+{
+ m_ram_size = size;
+}
+
+// Install a bank of real size (in K) actual and configured size
+// config, in memory map at address adr, in memory block at offset
+// radr, skipping off_s bytes at the start in supervisor mode and
+// off_u in user mode.
+
+// In the ST (non-e), the address is split into a column and row of 7
+// to 9 bits (128K to 2M). Smaller chips just do not have the top
+// column and row bits. The address is split in the middle, with
+// column in the high bits and row in the low. As a result a mismatch
+// between configuration and actual chip size requires breaking up and
+// rebuilding the address.
+
+// In the STE it's the same but the column and row bits are
+// interleaved, ensuring a linear behaviour at all times.
+
+offs_t st_mmu_device::remap_128_512(offs_t offset)
+{
+ return (offset & 0xff) | ((offset & 0xff00) << 1);
+}
+
+offs_t st_mmu_device::remap_128_2048(offs_t offset)
+{
+ return (offset & 0xff) | ((offset & 0xff00) << 2);
+}
+
+offs_t st_mmu_device::remap_512_128(offs_t offset)
+{
+ return (offset & 0xff) | ((offset & 0x1fe00) >> 1);
+}
+
+offs_t st_mmu_device::remap_512_2048(offs_t offset)
+{
+ return (offset & 0x1ff) | ((offset & 0x3fe00) << 1);
+}
+
+offs_t st_mmu_device::remap_2048_128(offs_t offset)
+{
+ return (offset & 0xff) | ((offset & 0x1fc00) >> 2);
+}
+
+offs_t st_mmu_device::remap_2048_512(offs_t offset)
+{
+ return (offset & 0x1ff) | ((offset & 0x7fc00) >> 1);
+}
+
+void st_mmu_device::ram_mapping(u32 actual, u32 config, u32 adr, u32 radr, u32 off_s, u32 off_u)
+{
+ auto &ss = m_cpu->space(AS_PROGRAM);
+ auto &su = m_cpu->space(m68000_device::AS_USER_PROGRAM);
+ switch(config) {
+ case 128:
+ switch(actual) {
+ case 0: {
+ ss.unmap_readwrite(adr + off_s, adr + 0x1ffff);
+ su.unmap_readwrite(adr + off_u, adr + 0x1ffff);
+ break;
+ }
+ case 128: {
+ ss.install_ram(adr + off_s, adr + 0x1ffff, m_ram + radr/2 + off_s/2);
+ su.install_ram(adr + off_u, adr + 0x1ffff, m_ram + radr/2 + off_u/2);
+ break;
+ }
+ case 512: {
+ ss.install_read_handler (adr + off_s, adr + 0x1ffff, read16sm_delegate(*this, [this, off_s, radr](offs_t offset) { return m_ram[remap_128_512(offset + off_s/2) + radr/2]; }, "128-512"));
+ ss.install_write_handler(adr + off_s, adr + 0x1ffff, write16s_delegate(*this, [this, off_s, radr](offs_t offset, offs_t data, offs_t mem_mask) { COMBINE_DATA(&m_ram[remap_128_512(offset + off_s/2) + radr/2]); }, "128-512"));
+ su.install_read_handler (adr + off_u, adr + 0x1ffff, read16sm_delegate(*this, [this, off_u, radr](offs_t offset) { return m_ram[remap_128_512(offset + off_u/2) + radr/2]; }, "128-512"));
+ su.install_write_handler(adr + off_u, adr + 0x1ffff, write16s_delegate(*this, [this, off_u, radr](offs_t offset, offs_t data, offs_t mem_mask) { COMBINE_DATA(&m_ram[remap_128_512(offset + off_u/2) + radr/2]); }, "128-512"));
+ break;
+ }
+ case 2048: {
+ ss.install_read_handler (adr + off_s, adr + 0x1ffff, read16sm_delegate(*this, [this, off_s, radr](offs_t offset) { return m_ram[remap_128_2048(offset + off_s/2) + radr/2]; }, "128-2048"));
+ ss.install_write_handler(adr + off_s, adr + 0x1ffff, write16s_delegate(*this, [this, off_s, radr](offs_t offset, offs_t data, offs_t mem_mask) { COMBINE_DATA(&m_ram[remap_512_128(offset + off_s/2) + radr/2]); }, "128-2048"));
+ su.install_read_handler (adr + off_u, adr + 0x1ffff, read16sm_delegate(*this, [this, off_u, radr](offs_t offset) { return m_ram[remap_128_2048(offset + off_u/2) + radr/2]; }, "128-2048"));
+ su.install_write_handler(adr + off_u, adr + 0x1ffff, write16s_delegate(*this, [this, off_u, radr](offs_t offset, offs_t data, offs_t mem_mask) { COMBINE_DATA(&m_ram[remap_512_128(offset + off_u/2) + radr/2]); }, "128-2048"));
+ break;
+ }
+ }
+ break;
+ case 512:
+ switch(actual) {
+ case 0: {
+ ss.unmap_readwrite(adr + off_s, adr + 0x7ffff);
+ su.unmap_readwrite(adr + off_u, adr + 0x7ffff);
+ break;
+ }
+ case 128: {
+ ss.install_read_handler (adr + off_s, adr + 0x7ffff, read16sm_delegate(*this, [this, off_s, radr](offs_t offset) { return m_ram[remap_512_128(offset + off_s/2) + radr/2]; }, "512-128"));
+ ss.install_write_handler(adr + off_s, adr + 0x7ffff, write16s_delegate(*this, [this, off_s, radr](offs_t offset, offs_t data, offs_t mem_mask) { COMBINE_DATA(&m_ram[remap_512_128(offset + off_s/2) + radr/2]); }, "512-128"));
+ su.install_read_handler (adr + off_u, adr + 0x7ffff, read16sm_delegate(*this, [this, off_u, radr](offs_t offset) { return m_ram[remap_512_128(offset + off_u/2) + radr/2]; }, "512-128"));
+ su.install_write_handler(adr + off_u, adr + 0x7ffff, write16s_delegate(*this, [this, off_u, radr](offs_t offset, offs_t data, offs_t mem_mask) { COMBINE_DATA(&m_ram[remap_512_128(offset + off_u/2) + radr/2]); }, "512-128"));
+ break;
+ }
+ case 512: {
+ ss.install_ram(adr + off_s, adr + 0x7ffff, m_ram + radr/2 + off_s/2);
+ su.install_ram(adr + off_u, adr + 0x7ffff, m_ram + radr/2 + off_u/2);
+ break;
+ }
+ case 2048: {
+ ss.install_read_handler (adr + off_s, adr + 0x7ffff, read16sm_delegate(*this, [this, off_s, radr](offs_t offset) { return m_ram[remap_512_2048(offset + off_s/2) + radr/2]; }, "512-2048"));
+ ss.install_write_handler(adr + off_s, adr + 0x7ffff, write16s_delegate(*this, [this, off_s, radr](offs_t offset, offs_t data, offs_t mem_mask) { COMBINE_DATA(&m_ram[remap_512_128(offset + off_s/2) + radr/2]); }, "512-2048"));
+ su.install_read_handler (adr + off_u, adr + 0x7ffff, read16sm_delegate(*this, [this, off_u, radr](offs_t offset) { return m_ram[remap_512_2048(offset + off_u/2) + radr/2]; }, "512-2048"));
+ su.install_write_handler(adr + off_u, adr + 0x7ffff, write16s_delegate(*this, [this, off_u, radr](offs_t offset, offs_t data, offs_t mem_mask) { COMBINE_DATA(&m_ram[remap_512_128(offset + off_u/2) + radr/2]); }, "512-2048"));
+ break;
+ }
+ }
+ break;
+ case 2048:
+ switch(actual) {
+ case 0: {
+ ss.unmap_readwrite(adr + off_s, adr + 0x1fffff);
+ su.unmap_readwrite(adr + off_u, adr + 0x1fffff);
+ break;
+ }
+ case 128: {
+ ss.install_read_handler (adr + off_s, adr + 0x1fffff, read16sm_delegate(*this, [this, off_s, radr](offs_t offset) { return m_ram[remap_2048_128(offset + off_s/2) + radr/2]; }, "2048-128"));
+ ss.install_write_handler(adr + off_s, adr + 0x1fffff, write16s_delegate(*this, [this, off_s, radr](offs_t offset, offs_t data, offs_t mem_mask) { COMBINE_DATA(&m_ram[remap_2048_128(offset + off_s/2) + radr/2]); }, "2048-128"));
+ su.install_read_handler (adr + off_u, adr + 0x1fffff, read16sm_delegate(*this, [this, off_u, radr](offs_t offset) { return m_ram[remap_2048_128(offset + off_u/2) + radr/2]; }, "2048-128"));
+ su.install_write_handler(adr + off_u, adr + 0x1fffff, write16s_delegate(*this, [this, off_u, radr](offs_t offset, offs_t data, offs_t mem_mask) { COMBINE_DATA(&m_ram[remap_2048_128(offset + off_u/2) + radr/2]); }, "2048-128"));
+ break;
+ }
+ case 512: {
+ ss.install_read_handler (adr + off_s, adr + 0x1fffff, read16sm_delegate(*this, [this, off_s, radr](offs_t offset) { return m_ram[remap_2048_512(offset + off_s/2) + radr/2]; }, "2048-512"));
+ ss.install_write_handler(adr + off_s, adr + 0x1fffff, write16s_delegate(*this, [this, off_s, radr](offs_t offset, offs_t data, offs_t mem_mask) { COMBINE_DATA(&m_ram[remap_2048_512(offset + off_s/2) + radr/2]); }, "2048-512"));
+ su.install_read_handler (adr + off_u, adr + 0x1fffff, read16sm_delegate(*this, [this, off_u, radr](offs_t offset) { return m_ram[remap_2048_512(offset + off_u/2) + radr/2]; }, "2048-512"));
+ su.install_write_handler(adr + off_u, adr + 0x1fffff, write16s_delegate(*this, [this, off_u, radr](offs_t offset, offs_t data, offs_t mem_mask) { COMBINE_DATA(&m_ram[remap_2048_512(offset + off_u/2) + radr/2]); }, "2048-512"));
+ break;
+ }
+ case 2048: {
+ ss.install_ram(adr + off_s, adr + 0x1fffff, m_ram + radr/2 + off_s/2);
+ su.install_ram(adr + off_u, adr + 0x1fffff, m_ram + radr/2 + off_u/2);
+ break;
+ }
+ }
+ break;
+ }
+}
+
+void st_mmu_device::configure_ram()
+{
+ u32 b0 = 0, b1 = 0;
+ switch(m_ram_size) {
+ case 256*1024: b0 = 128; b1 = 128; break;
+ case 512*1024: b0 = 512; b1 = 0; break;
+ case 1024*1024: b0 = 512; b1 = 512; break;
+ case 2048*1024: b0 = 2048; b1 = 0; break;
+ case 4096*1024: b0 = 2048; b1 = 2048; break;
+ }
+
+ const u32 bank_sizes[4] = { 128, 512, 2048, 0 };
+ u32 c0 = bank_sizes[(m_memcfg >> 2) & 3];
+ u32 c1 = bank_sizes[m_memcfg & 3];
+
+ logerror("ram banks %d/%d configured %d/%d\n", b0, b1, c0, c1);
+
+ constexpr u32 st_s = 0x000008;
+ constexpr u32 st_u = 0x000800;
+
+ ram_mapping(b0, c0, 0, 0, st_s, st_u);
+ ram_mapping(b1, c1, 1024*c0, 1024*b0, 0, 0);
+
+ u32 ub = 1024*(c0+c1);
+ if(ub < 0x400000) {
+ m_cpu->space(AS_PROGRAM).nop_readwrite(ub, 0x3fffff);
+ m_cpu->space(m68000_device::AS_USER_PROGRAM).nop_readwrite(ub, 0x3fffff);
+ }
+}
diff --git a/src/mame/atari/stmmu.h b/src/mame/atari/stmmu.h
new file mode 100644
index 00000000000..913087dc929
--- /dev/null
+++ b/src/mame/atari/stmmu.h
@@ -0,0 +1,105 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder, Olivier Galibert
+
+#ifndef MAME_ATARI_STMMU_H
+#define MAME_ATARI_STMMU_H
+
+#include <machine/wd_fdc.h>
+#include <cpu/m68000/m68000.h>
+
+// Atari ST family MMU implementation. Handles things from the GLUE
+// too, because the concerns are difficult to separate
+
+// Manages dma and communications with fdc and hd in general.
+
+class st_mmu_device : public device_t {
+public:
+ st_mmu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+
+ template <typename T> void set_ram(T &&tag) { m_ram.set_tag(std::forward<T>(tag)); }
+ template <typename T> void set_cpu(T &&tag) { m_cpu.set_tag(std::forward<T>(tag)); }
+ template <typename T> void set_fdc(T &&tag) { m_fdc.set_tag(std::forward<T>(tag)); }
+
+ void map(address_map &map);
+ void set_ram_size(u32 size);
+
+ DECLARE_WRITE_LINE_MEMBER(fdc_drq_w);
+ DECLARE_WRITE_LINE_MEMBER(hdc_drq_w);
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
+ enum {
+ STATUS_DRQ = 0x04,
+ STATUS_SECTOR_COUNT = 0x02,
+ STATUS_ERROR = 0x01,
+ };
+
+ enum {
+ MODE_READ_WRITE = 0x100,
+ MODE_FDC_HDC_ACK = 0x080,
+ MODE_ENABLED = 0x040,
+ MODE_SECTOR_COUNT = 0x010,
+ MODE_FDC_HDC_CS = 0x008,
+ MODE_A1 = 0x004,
+ MODE_A0 = 0x002,
+ MODE_ADDRESS_MASK = 0x006,
+ };
+
+ enum {
+ SECTOR_SIZE = 512
+ };
+
+ required_shared_ptr<u16> m_ram;
+ required_device<m68000_device> m_cpu;
+ required_device<wd1772_device> m_fdc;
+
+ uint32_t m_ram_size;
+
+ uint32_t m_dma_address;
+ uint16_t m_dma_mode;
+ uint16_t m_fifo[16];
+ uint8_t m_sector_count, m_block_count;
+ uint8_t m_fifo_index;
+ uint8_t m_memcfg;
+ bool m_fdc_drq, m_hdc_drq;
+ bool m_dma_no_error;
+
+ uint16_t data_r();
+ void data_w(uint16_t data);
+ uint16_t dma_status_r();
+ void dma_mode_w(uint16_t data);
+ uint8_t dma_address_h_r();
+ uint8_t dma_address_m_r();
+ uint8_t dma_address_l_r();
+ void dma_address_h_w(uint8_t data);
+ void dma_address_m_w(uint8_t data);
+ void dma_address_l_w(uint8_t data);
+
+ uint8_t memcfg_r();
+ void memcfg_w(uint8_t data);
+ void configure_ram();
+ static offs_t remap_128_512(offs_t offset);
+ static offs_t remap_128_2048(offs_t offset);
+ static offs_t remap_512_128(offs_t offset);
+ static offs_t remap_512_2048(offs_t offset);
+ static offs_t remap_2048_128(offs_t offset);
+ static offs_t remap_2048_512(offs_t offset);
+ void ram_mapping(u32 actual, u32 config, u32 adr, u32 radr, u32 off_s, u32 off_u);
+
+ void fdc_transfer();
+ void hdc_transfer();
+
+ void fifo_flush();
+ u8 fifo_pop();
+ void fifo_push(u8 data);
+
+ void fifo_schedule_block_transfer_to_ram();
+ void fifo_schedule_block_transfer_from_ram();
+};
+
+DECLARE_DEVICE_TYPE(ST_MMU, st_mmu_device)
+
+#endif