atarist: Extract the MMU, will need STE memory map specialization

This commit is contained in:
Olivier Galibert 2022-12-19 11:47:08 +01:00
parent aebf6eddd8
commit 82814d3b50
4 changed files with 672 additions and 521 deletions

View File

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

View File

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

501
src/mame/atari/stmmu.cpp Normal file
View File

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

105
src/mame/atari/stmmu.h Normal file
View File

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