From 82814d3b50831a1d9a67ca26a317b31a76bb904e Mon Sep 17 00:00:00 2001 From: Olivier Galibert Date: Mon, 19 Dec 2022 11:47:08 +0100 Subject: [PATCH] atarist: Extract the MMU, will need STE memory map specialization --- src/devices/cpu/m68000/m68000.cpp | 2 +- src/mame/atari/atarist.cpp | 585 ++++-------------------------- src/mame/atari/stmmu.cpp | 501 +++++++++++++++++++++++++ src/mame/atari/stmmu.h | 105 ++++++ 4 files changed, 672 insertions(+), 521 deletions(-) create mode 100644 src/mame/atari/stmmu.cpp create mode 100644 src/mame/atari/stmmu.h 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 m_maincpu; + memory_share_creator m_mainram; required_device m_ikbd; + required_device m_mmu; optional_device m_stb; required_device m_fdc; required_device_array m_floppy; @@ -147,55 +137,17 @@ protected: required_device_array m_acia; required_device m_centronics; required_device m_cart; - required_device m_ram; + required_device m_ramcfg; required_device m_rs232; required_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; @@ -324,365 +277,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 +#include + +// 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 void set_ram(T &&tag) { m_ram.set_tag(std::forward(tag)); } + template void set_cpu(T &&tag) { m_cpu.set_tag(std::forward(tag)); } + template void set_fdc(T &&tag) { m_fdc.set_tag(std::forward(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 m_ram; + required_device m_cpu; + required_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