sun4: checkpoint (nw)

This commit is contained in:
arbee 2016-06-20 21:24:06 -04:00
parent 2005b3ae3f
commit 7d4cfb098a

View File

@ -1,5 +1,5 @@
// license:BSD-3-Clause
// copyright-holders:Miodrag Milanovic
// copyright-holders:Miodrag Milanovic, R. Belmont, Ryan Holtz
/***************************************************************************
Sun-4 Models
@ -379,38 +379,55 @@
high 3.5" disks. Code name "Scorpion". First
supported in Solaris 2.2 (SunOS 5.2).
21/11/2011 Skeleton driver.
20/06/2016 Much less skeletony.
4/60 memory test notes:
ffe809fc: call to print "Sizing Memory" to the UART
ffe80a04: set o0 to 0xf0000000, a valid PTE that points to absolute zero in main RAM
ffe80a08: call to set that PTE in the page table (routine also reads back the written value and verifies that the unused bits are all 0)
ffe80a0c: stash g0, the current memory base testing, to o2, which the CALL above uses as the virtual address to set the PTE for
ffe80a10: set o0 to 0xf0000400, a valid PTE that points to the 4 MB mark (0x400000) in main RAM
ffe80a14: call to set that PTE in the page table
ffe80a18: set o2 to 0x00001000, so virtual address 0x1000 now points to physical 0x400000
ffe80a1c: set i7 to 0x01000000, which indicates the memory size is 64MB if everything passes
ffe80a20: store i7 at g0, which is currently 0
ffe80a24: SRL i7 by 2, now 0x00400000, so if the next store fails on a bus error memory size is 4 MB
ffe80a28: store the new i7 at o2, which is 0x400000
ffe80a2c: store succeeded! load [g0] to i7, ta-da, 64 MB RAM sized
****************************************************************************/
#include "emu.h"
#include "cpu/sparc/sparc.h"
#include "machine/timekpr.h"
#include "machine/ram.h"
#include "machine/z80scc.h"
#include "machine/bankdev.h"
#include "machine/nvram.h"
#include "bus/rs232/rs232.h"
#define ENA_NOTBOOT 0x80
#define ENA_SDVMA 0x20
#define ENA_CACHE 0x10
#define ENA_RESET 0x04
#define ENA_DIAG 0x01
#define SCC1_TAG "kbdmouse"
#define SCC2_TAG "uart"
#define TIMEKEEPER_TAG "timekpr"
#define SCC1_TAG "scc1"
#define SCC2_TAG "scc2"
#define RS232A_TAG "rs232a"
#define RS232B_TAG "rs232b"
#define ASI_SYSTEM_SPACE 2
#define ASI_SEGMENT_MAP 3
#define ASI_PAGE_MAP 4
#define ASI_USER_INSN 8
#define ASI_SUPER_INSN 9
#define ASI_USER_DATA 10
#define ASI_SUPER_DATA 11
#define ASI_FLUSH_SEGMENT 12
#define ASI_FLUSH_PAGE 13
#define ASI_FLUSH_CONTEXT 14
#define ENA_NOTBOOT (0x80)
#define ENA_SDVMA (0x20)
#define ENA_CACHE (0x10)
#define ENA_RESET (0x04)
#define ENA_DIAG (0x01)
// page table entry constants
#define PM_VALID (0x80000000) // page is valid
#define PM_WRITEMASK (0x40000000) // writable?
#define PM_SYSMASK (0x20000000) // system use only?
#define PM_CACHE (0x10000000) // cachable?
#define PM_TYPEMASK (0x0c000000) // type mask
#define PM_ACCESSED (0x02000000) // accessed flag
#define PM_MODIFIED (0x01000000) // modified flag
class sun4_state : public driver_device
{
@ -418,11 +435,13 @@ public:
sun4_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag)
, m_maincpu(*this, "maincpu")
, m_scc1(*this, SCC1_TAG)
, m_scc2(*this, SCC2_TAG)
, m_type0space(*this, "type0")
, m_type1space(*this, "type1")
, m_ram(*this, RAM_TAG)
, m_rom(*this, "user1")
, m_kbdmouse(*this, SCC1_TAG)
, m_uart(*this, SCC2_TAG)
, m_rom_ptr(nullptr)
, m_context(0)
, m_system_enable(0)
{
}
@ -432,184 +451,140 @@ public:
DECLARE_READ32_MEMBER( sun4_mmu_r );
DECLARE_WRITE32_MEMBER( sun4_mmu_w );
DECLARE_READ32_MEMBER( ram_r );
DECLARE_WRITE32_MEMBER( ram_w );
DECLARE_READ32_MEMBER( ss1_sl0_id );
DECLARE_READ32_MEMBER( ss1_sl3_id );
protected:
required_device<mb86901_device> m_maincpu;
required_device<z80scc_device> m_scc1;
required_device<z80scc_device> m_scc2;
optional_device<address_map_bank_device> m_type0space, m_type1space;
required_device<ram_device> m_ram;
required_memory_region m_rom;
required_device<z80scc_device> m_kbdmouse;
required_device<z80scc_device> m_uart;
UINT32 read_supervisor_data(UINT32 vaddr, UINT32 mem_mask);
void write_supervisor_data(UINT32 vaddr, UINT32 data, UINT32 mem_mask);
UINT32 *m_rom_ptr;
UINT32 m_context;
UINT16 m_segmap[8][4096];
UINT32 m_pagemap[8192];
UINT32 m_system_enable;
private:
UINT32 *m_ram_ptr;
UINT8 m_segmap[8][4096];
UINT32 m_pagemap[8192];
UINT32 m_ram_size, m_ram_size_words;
};
#define SEGMENT(vaddr) m_segmap[m_context & 7][((vaddr) >> 18) & 0xfff]
#define PAGE(vaddr) m_pagemap[((m_segmap[m_context & 7][((vaddr) >> 18) & 0xfff] & 0x7f) << 6) | (((vaddr) >> 12) & 0x3f)]
#define PADDR(vaddr) (((PAGE(vaddr) << 12) & 0x0ffff000) | ((vaddr) & 0xfff))
UINT32 sun4_state::read_supervisor_data(UINT32 vaddr, UINT32 mem_mask)
{
UINT32 page = PAGE(vaddr);
bool v = (page & 0x80000000) ? true : false;
bool w = (page & 0x40000000) ? true : false;
bool s = (page & 0x20000000) ? true : false;
bool x = (page & 0x10000000) ? true : false;
int t = (page & 0x0c000000) >> 26;
bool a = (page & 0x02000000) ? true : false;
bool m = (page & 0x01000000) ? true : false;
char mode[4] = { 'M', 'S', '0', '1' };
logerror("supervisor data read: vaddr %08x, paddr %08x, context %d, segment entry %02x, page entry %08x, %c%c%c%c%c%c%c\n", vaddr, PADDR(vaddr), m_context, SEGMENT(vaddr), PAGE(vaddr)
, v ? 'V' : 'v', w ? 'W' : 'w', s ? 'S' : 's', x ? 'X' : 'x', mode[t], a ? 'A' : 'a', m ? 'M' : 'm');
return 0;
}
void sun4_state::write_supervisor_data(UINT32 vaddr, UINT32 data, UINT32 mem_mask)
{
UINT32 page = PAGE(vaddr);
bool v = (page & 0x80000000) ? true : false;
bool w = (page & 0x40000000) ? true : false;
bool s = (page & 0x20000000) ? true : false;
bool x = (page & 0x10000000) ? true : false;
int t = (page & 0x0c000000) >> 26;
bool a = (page & 0x02000000) ? true : false;
bool m = (page & 0x01000000) ? true : false;
char mode[4] = { 'M', 'S', '0', '1' };
logerror("supervisor data write: vaddr %08x, paddr %08x, data %08x, mem_mask %08x, context %d, segment entry %02x, page entry %08x, %c%c%c%c%c%c%c\n", vaddr, PADDR(vaddr), data, mem_mask,
m_context, SEGMENT(vaddr), PAGE(vaddr), v ? 'V' : 'v', w ? 'W' : 'w', s ? 'S' : 's', x ? 'X' : 'x', mode[t], a ? 'A' : 'a', m ? 'M' : 'm');
}
READ32_MEMBER( sun4_state::sun4_mmu_r )
{
UINT8 asi = m_maincpu->get_asi();
int page;
if (!space.debugger_access())
{
switch(asi)
{
case ASI_SYSTEM_SPACE:
switch (offset >> 26)
{
case 3: // context reg
logerror("sun4: read context register %08x (& %08x) asi 2, offset %x, PC = %x\n", m_context << 24, mem_mask, offset << 2, m_maincpu->pc());
return m_context << 24;
case 4: // system enable reg
logerror("sun4: read system enable register %08x (& %08x) asi 2, offset %x, PC = %x\n", m_system_enable << 24, mem_mask, offset << 2, m_maincpu->pc());
return m_system_enable << 24;
case 8: // (d-)cache tags
logerror("sun4: read dcache tags %08x (& %08x) asi 2, offset %x, PC = %x\n", 0xffffffff, mem_mask, offset << 2, m_maincpu->pc());
return 0xffffffff;
case 9: // (d-)cache data
logerror("sun4: read dcache data %08x (& %08x) asi 2, offset %x, PC = %x\n", 0xffffffff, mem_mask, offset << 2, m_maincpu->pc());
return 0xffffffff;
case 15: // Type 1 space passthrough
switch ((offset >> 22) & 15)
{
case 0: // keyboard/mouse
switch (offset & 1)
{
case 0:
{
UINT32 ret = 0;
if (mem_mask & 0xffff0000)
ret |= m_kbdmouse->cb_r(space, 0) << 24;
if (mem_mask & 0x0000ffff)
ret |= m_kbdmouse->db_r(space, 0) << 8;
return ret;
}
case 1:
{
UINT32 ret = 0;
if (mem_mask & 0xffff0000)
ret |= m_kbdmouse->ca_r(space, 0) << 24;
if (mem_mask & 0x0000ffff)
ret |= m_kbdmouse->da_r(space, 0) << 8;
return ret;
}
}
break;
case 1: // serial ports
switch (offset & 1)
{
case 0:
{
UINT32 ret = 0;
if (mem_mask & 0xffff0000)
ret |= m_uart->cb_r(space, 0) << 24;
if (mem_mask & 0x0000ffff)
ret |= m_uart->db_r(space, 0) << 8;
return ret;
}
case 1:
{
UINT32 ret = 0;
if (mem_mask & 0xffff0000)
ret |= m_uart->ca_r(space, 0) << 24;
if (mem_mask & 0x0000ffff)
ret |= m_uart->da_r(space, 0) << 8;
return ret;
}
}
break;
default:
logerror("sun4: read unknown type 1 space at address %x (& %08x) asi 2, offset %x, PC = %x\n", offset << 2, mem_mask, offset << 2, m_maincpu->pc());
}
break;
case 0: // IDPROM - TODO: SPARCstation-1 does not have an ID prom and a timeout should occur.
default:
logerror("sun4: read unknown register (& %08x) asi 2, offset %x, PC = %x\n", mem_mask, offset << 2, m_maincpu->pc());
return 0;
}
break;
case ASI_SEGMENT_MAP:
{
logerror("sun4: read m_segmap[%d][(%08x >> 18) & 0xfff = %03x] = %08x << 24 & %08x\n", m_context & 7, offset << 2, (offset >> 16) & 0xfff, SEGMENT(offset << 2), mem_mask);
UINT32 result = SEGMENT(offset << 2);
while (!(mem_mask & 1))
{
mem_mask >>= 1;
result <<= 1;
}
return result;
}
case ASI_PAGE_MAP: // page map
{
logerror("sun4: read m_pagemap[(m_segmap[%d][(%08x >> 18) & 0xfff = %03x] = %08x << 6) | ((%08x >> 12) & 0x3f)]] = %08x & %08x\n", m_context & 7, offset << 2, (offset >> 16) & 0xfff, SEGMENT(offset << 2), offset << 2, PAGE(offset << 2), mem_mask);
return PAGE(offset << 2);
}
case ASI_SUPER_INSN: // supervisor instruction space
return m_rom_ptr[offset & 0x1ffff]; // wrong, but works for now
case ASI_SUPER_DATA:
return read_supervisor_data(offset << 2, mem_mask);
default:
logerror("sun4: read (& %08x) asi %d byte offset %x, PC = %x\n", mem_mask, asi, offset << 2, m_maincpu->pc());
break;
}
}
if (!(m_system_enable & ENA_NOTBOOT))
if (space.debugger_access()) return m_rom_ptr[offset & 0x1ffff];
// supervisor program fetches in boot state are special
if ((!(m_system_enable & ENA_NOTBOOT)) && (asi == 9))
{
return m_rom_ptr[offset & 0x1ffff];
}
switch (asi)
{
case 2: // system space
switch (offset >> 26)
{
case 3: // context reg
return m_context<<24;
case 4: // system enable reg
return m_system_enable;
case 6: // bus error register
return 0;
case 8: // (d-)cache tags
logerror("sun4: read dcache tags @ %x, PC = %x\n", offset, m_maincpu->pc());
return 0xffffffff;
case 9: // (d-)cache data
logerror("sun4: read dcache data @ %x, PC = %x\n", offset, m_maincpu->pc());
return 0xffffffff;
case 0xf: // UART bypass
//printf("read UART bypass @ %x mask %08x\n", offset<<2, mem_mask);
switch (offset & 3)
{
case 0: if (mem_mask == 0xff000000) return m_scc1->cb_r(space, offset)<<24; else return m_scc1->db_r(space, offset)<<8; break;
case 1: if (mem_mask == 0xff000000) return m_scc1->ca_r(space, offset)<<24; else return m_scc1->da_r(space, offset)<<8; break;
}
return 0xffffffff;
case 0: // IDPROM - TODO: SPARCstation-1 does not have an ID prom and a timeout should occur.
default:
printf("sun4: ASI 2 space unhandled read @ %x (PC=%x)\n", offset<<2, m_maincpu->pc());
return 0;
}
break;
case 3: // segment map
//printf("sun4: read segment map @ %x (entry %d, mem_mask %08x, PC=%x)\n", offset << 2, (offset>>16) & 0xfff, mem_mask, m_maincpu->pc());
return m_segmap[m_context][(offset>>16) & 0xfff]<<24;
break;
case 4: // page map
page = m_segmap[m_context & 7][(offset >> 16) & 0xfff] << 6;
page += (offset >> 10) & 0x3f;
//printf("sun4: read page map @ %x (entry %d, mem_mask %08x, PC=%x)\n", offset << 2, page, mem_mask, m_maincpu->pc());
return m_pagemap[page];
break;
case 8:
case 9:
case 10:
case 11:
{
// it's translation time
UINT8 pmeg = m_segmap[m_context & 7][(offset >> 16) & 0xfff];
UINT32 entry = (pmeg << 6) + ((offset >> 10) & 0x3f);
if (m_pagemap[entry] & PM_VALID)
{
m_pagemap[entry] |= PM_ACCESSED;
UINT32 tmp = (m_pagemap[entry] & 0xffff) << 10;
tmp |= (offset & 0x3ff);
//printf("sun4: translated vaddr %08x to phys %08x type %d, PTE %08x, PC=%x\n", offset<<2, tmp<<2, (m_pagemap[entry]>>26) & 3, m_pagemap[entry], m_maincpu->pc());
switch ((m_pagemap[entry] >> 26) & 3)
{
case 0: // type 0 space
return m_type0space->read32(space, tmp, mem_mask);
case 1: // type 1 space
// magic EPROM bypass
if ((tmp >= (0x6000000>>2)) && (tmp <= (0x6ffffff>>2)))
{
return m_rom_ptr[offset & 0x1ffff];
}
//printf("Read type 1 @ VA %08x, phys %08x\n", offset<<2, tmp<<2);
return m_type1space->read32(space, tmp, mem_mask);
default:
printf("sun4: access to memory type not defined in sun4c\n");
return 0;
}
}
else
{
printf("sun4: INVALID PTE accessed! PC=%x\n", m_maincpu->pc());
}
}
break;
default:
if (!space.debugger_access()) printf("sun4: ASI %d unhandled read @ %x (PC=%x)\n", asi, offset<<2, m_maincpu->pc());
return 0;
}
printf("sun4: read asi %d byte offset %x, PC = %x\n", asi, offset << 2, m_maincpu->pc());
return 0;
}
@ -617,109 +592,107 @@ READ32_MEMBER( sun4_state::sun4_mmu_r )
WRITE32_MEMBER( sun4_state::sun4_mmu_w )
{
UINT8 asi = m_maincpu->get_asi();
int page;
//printf("sun4: write %08x to %08x (ASI %d, mem_mask %08x, PC %x)\n", data, offset, asi, mem_mask, m_maincpu->pc());
switch (asi)
{
case 2:
switch (offset >> 26)
{
case 3: // context reg
logerror("sun4: %08x (& %08x) asi 2 to context register, offset %x, PC = %x\n", data, mem_mask, offset << 2, m_maincpu->pc());
m_context = (UINT8)(data >> 24) & 7;
return;
case 4: // system enable reg
logerror("sun4: write %08x (& %08x) asi 2 to system enable register, offset %x, PC = %x\n", data, mem_mask, offset << 2, m_maincpu->pc());
m_system_enable = (UINT8)data;
return;
case 8: // cache tags
logerror("sun4: write %08x (& %08x) asi 2 to cache tags @ %x, PC = %x\n", data, mem_mask, offset << 2, m_maincpu->pc());
return;
case 9: // cache data
logerror("sun4: write %08x (& %08x) asi 2 to cache data @ %x, PC = %x\n", data, mem_mask, offset << 2, m_maincpu->pc());
return;
case 15: // Type 1 space passthrough
switch ((offset >> 22) & 15)
{
case 0: // keyboard/mouse
switch (offset & 1)
{
case 0:
if (mem_mask & 0xffff0000)
m_kbdmouse->cb_w(space, 0, data >> 24);
if (mem_mask & 0x0000ffff)
m_kbdmouse->db_w(space, 0, data >> 24);
break;
case 1:
if (mem_mask & 0xffff0000)
m_kbdmouse->ca_w(space, 0, data >> 24);
if (mem_mask & 0x0000ffff)
m_kbdmouse->da_w(space, 0, data >> 24);
break;
}
break;
case 1: // serial ports
switch (offset & 1)
{
case 0:
if (mem_mask & 0xffff0000)
m_uart->cb_w(space, 0, data >> 24);
if (mem_mask & 0x0000ffff)
m_uart->db_w(space, 0, data >> 24);
break;
case 1:
if (mem_mask & 0xffff0000)
m_uart->ca_w(space, 0, data >> 24);
if (mem_mask & 0x0000ffff)
m_uart->da_w(space, 0, data >> 24);
break;
}
break;
default:
logerror("sun4: write unknown type 1 space %08x (& %08x) asi 2, offset %x, PC = %x\n", data, mem_mask, offset << 2, m_maincpu->pc());
}
break;
case 0: // IDPROM
default:
logerror("sun4: write %08x (& %08x) asi 2 to unknown register, offset %x, PC = %x\n", data, mem_mask, offset << 2, m_maincpu->pc());
return;
}
break;
case 3: // segment map
offset <<= 2;
while (!(mem_mask & 1))
{
mem_mask >>= 1;
data >>= 1;
}
SEGMENT(offset) = data;
//m_segmap[m_context & 7][(offset >> 18) & 0xfff] &= ~(mem_mask >> 16);
//m_segmap[m_context & 7][(offset >> 18) & 0xfff] |= (data >> 16) & (mem_mask >> 16);
logerror("sun4: write m_segmap[%d][(%08x >> 18) & 0xfff = %03x] = %08x & %08x\n", m_context & 7, offset << 2, (offset >> 16) & 0xfff, data, mem_mask);
break;
case ASI_PAGE_MAP: // page map
case 2:
switch (offset >> 26)
{
logerror("sun4: write m_pagemap[(m_segmap[%d][(%08x >> 18) & 0xfff = %03x] = %08x << 6) | ((%08x >> 12) & 0x3f)]] = %08x & %08x\n", m_context & 7, offset << 2,
(offset >> 16) & 0xfff, SEGMENT(offset << 2), offset << 2, data, mem_mask);
COMBINE_DATA(&PAGE(offset << 2));
PAGE(offset << 2) &= 0xff00ffff;
break;
case 3: // context reg
printf("%08x to context, mask %08x\n", data, mem_mask);
m_context = (UINT8)data<<24;
return;
case 4: // system enable reg
m_system_enable = (UINT8)data;
return;
case 8: // cache tags
logerror("sun4: %08x to cache tags @ %x, PC = %x\n", data, offset, m_maincpu->pc());
return;
case 9: // cache data
logerror("sun4: %08x to cache data @ %x, PC = %x\n", data, offset, m_maincpu->pc());
return;
case 0xf: // UART bypass
//printf("%08x to UART @ %d, mask %08x\n", data, offset & 3, mem_mask);
switch (offset & 3)
{
case 0: if (mem_mask == 0xff000000) m_scc1->cb_w(space, offset, data>>24); else m_scc1->db_w(space, offset, data>>8); break;
case 1: if (mem_mask == 0xff000000) m_scc1->ca_w(space, offset, data>>24); else { m_scc1->da_w(space, offset, data>>8); printf("%c", data>>8); } break;
}
return;
case 0: // IDPROM
default:
printf("sun4: ASI 2 space unhandled write %x @ %x (mask %08x, PC=%x)\n", data, offset<<2, mem_mask, m_maincpu->pc());
return;
}
break;
case 3: // segment map
{
UINT8 segdata = 0;
if (mem_mask == 0xffff0000) segdata = (data >> 16) & 0x7f;
else if (mem_mask == 0xff000000) segdata = (data >> 24) & 0x7f;
else logerror("sun4: writing segment map with unknown mask %08x, PC=%x\n", mem_mask, m_maincpu->pc());
//printf("sun4: %08x to segment map @ %x (entry %d, mem_mask %08x, PC=%x)\n", segdata, offset << 2, (offset>>16) & 0xfff, mem_mask, m_maincpu->pc());
m_segmap[m_context & 7][(offset>>16) & 0xfff] = segdata; // only 7 bits of the segment are necessary
}
return;
case 4: // page map
page = m_segmap[m_context & 7][(offset >> 16) & 0xfff] << 6; // get the PMEG
page += (offset >> 10) & 0x3f; // add the offset
//printf("sun4: %08x to page map @ %x (entry %d, mem_mask %08x, PC=%x)\n", data, offset << 2, page, mem_mask, m_maincpu->pc());
COMBINE_DATA(&m_pagemap[page]);
m_pagemap[page] &= 0xff00ffff; // these 8 bits are cleared when written and tested as such
return;
case 8:
case 9:
case 10:
case 11:
// it's translation time
UINT8 pmeg = m_segmap[m_context & 7][(offset >> 16) & 0xfff];
UINT32 entry = (pmeg << 6) + ((offset >> 10) & 0x3f);
case ASI_SUPER_DATA:
write_supervisor_data(offset << 2, data, mem_mask);
break;
if (m_pagemap[entry] & PM_VALID)
{
m_pagemap[entry] |= PM_ACCESSED;
UINT32 tmp = (m_pagemap[entry] & 0xffff) << 10;
tmp |= (offset & 0x3ff);
//printf("sun4: translated vaddr %08x to phys %08x type %d, PTE %08x, PC=%x\n", offset<<2, tmp<<2, (m_pagemap[entry]>>26) & 3, m_pagemap[entry], m_maincpu->pc());
default:
logerror("sun4: write %08x (& %08x) to asi %d byte offset %x, PC = %x\n", data, mem_mask, asi, offset << 2, m_maincpu->pc());
break;
switch ((m_pagemap[entry] >> 26) & 3)
{
case 0: // type 0
m_type0space->write32(space, tmp, data, mem_mask);
return;
case 1: // type 1
//printf("write device space @ %x\n", tmp<<1);
m_type1space->write32(space, tmp, data, mem_mask);
return;
default:
printf("sun4: access to memory type not defined in sun4c\n");
return;
}
}
else
{
printf("sun4: INVALID PTE accessed! PC=%x\n", m_maincpu->pc());
}
break;
}
printf("sun4: %08x to asi %d byte offset %x, PC = %x, mask = %08x\n", data, asi, offset << 2, m_maincpu->pc(), mem_mask);
}
static ADDRESS_MAP_START(sun4_mem, AS_PROGRAM, 32, sun4_state)
@ -733,11 +706,116 @@ INPUT_PORTS_END
void sun4_state::machine_reset()
{
m_context = 0;
m_system_enable = 0;
}
void sun4_state::machine_start()
{
m_rom_ptr = (UINT32 *)m_rom->base();
m_ram_ptr = (UINT32 *)m_ram->pointer();
m_ram_size = m_ram->size();
m_ram_size_words = m_ram_size >> 2;
}
READ32_MEMBER( sun4_state::ram_r )
{
if (offset < m_ram_size_words) return m_ram_ptr[offset];
//printf("ram_r: DAEing on access to %08x\n", offset<<2);
m_maincpu->trap(SPARC_DATA_ACCESS_EXCEPTION);
return 0xffffffff;
}
WRITE32_MEMBER( sun4_state::ram_w )
{
#if 0
// if writing bad parity is enabled
if (((m_parregs[0] & 0x20000000) == 0x20000000) &&
(m_irqctrl & 0x01000000) &&
!(m_bInBusErr))
{
m_parregs[1] = offset<<2;
//printf("Generating parity error, mem_mask %08x\n", mem_mask);
switch (mem_mask)
{
case 0xff000000:
m_parregs[0] |= 0x08<<24;
break;
case 0x00ff0000:
m_parregs[1] += 1;
m_parregs[0] |= 0x04<<24;
break;
case 0x0000ff00:
m_parregs[1] += 2;
m_parregs[0] |= 0x02<<24;
break;
case 0x000000ff:
m_parregs[1] += 3;
m_parregs[0] |= 0x01<<24;
break;
case 0x0000ffff:
m_parregs[1] += 2;
m_parregs[0] |= 0x03<<24;
break;
case 0xffff0000:
m_parregs[0] |= 0x0c<<24;
break;
case 0xffffffff: // no address adjust, show all 4 lanes as problematic
m_parregs[0] |= 0x0f<<24;
break;
}
// indicate parity interrupt
m_parregs[0] |= 0x80000000;
// and can we take that now?
if (m_parregs[0] & 0x40000000)
{
}
}
#endif
if (offset < m_ram_size_words)
{
COMBINE_DATA(&m_ram_ptr[offset]);
return;
}
printf("ram_w: DAEing on access to %08x\n", offset<<2);
m_maincpu->trap(SPARC_DATA_ACCESS_EXCEPTION);
}
static ADDRESS_MAP_START(type0space_map, AS_PROGRAM, 32, sun4_state)
AM_RANGE(0x00000000, 0x03ffffff) AM_READWRITE(ram_r, ram_w)
ADDRESS_MAP_END
static ADDRESS_MAP_START(type1space_map, AS_PROGRAM, 32, sun4_state)
AM_RANGE(0x00000000, 0x0000000f) AM_DEVREADWRITE8(SCC1_TAG, z80scc_device, ba_cd_inv_r, ba_cd_inv_w, 0xff00ff00)
AM_RANGE(0x01000000, 0x0100000f) AM_DEVREADWRITE8(SCC2_TAG, z80scc_device, ba_cd_inv_r, ba_cd_inv_w, 0xff00ff00)
AM_RANGE(0x02000000, 0x020007ff) AM_DEVREADWRITE8(TIMEKEEPER_TAG, timekeeper_device, read, write, 0xffffffff)
AM_RANGE(0x06000000, 0x0607ffff) AM_ROM AM_REGION("user1", 0)
AM_RANGE(0x08000000, 0x08000003) AM_READ(ss1_sl0_id) // slot 0 contains SCSI/DMA/Ethernet
AM_RANGE(0x0e000000, 0x0e000003) AM_READ(ss1_sl3_id) // slot 3 contains video board
ADDRESS_MAP_END
// indicate 4/60 SCSI/DMA/Ethernet card exists
READ32_MEMBER( sun4_state::ss1_sl0_id )
{
return 0xfe810101;
}
// indicate 4/60 color video card exists
READ32_MEMBER( sun4_state::ss1_sl3_id )
{
return 0xfe010101;
}
static MACHINE_CONFIG_START( sun4, sun4_state )
@ -745,6 +823,26 @@ static MACHINE_CONFIG_START( sun4, sun4_state )
MCFG_CPU_ADD("maincpu", MB86901, 16670000)
MCFG_DEVICE_ADDRESS_MAP(AS_PROGRAM, sun4_mem)
MCFG_RAM_ADD(RAM_TAG)
MCFG_RAM_DEFAULT_SIZE("4M")
MCFG_RAM_DEFAULT_VALUE(0x00)
MCFG_M48T02_ADD(TIMEKEEPER_TAG)
// MMU Type 0 device space
MCFG_DEVICE_ADD("type0", ADDRESS_MAP_BANK, 0)
MCFG_DEVICE_PROGRAM_MAP(type0space_map)
MCFG_ADDRESS_MAP_BANK_ENDIANNESS(ENDIANNESS_BIG)
MCFG_ADDRESS_MAP_BANK_DATABUS_WIDTH(32)
MCFG_ADDRESS_MAP_BANK_STRIDE(0x80000000)
// MMU Type 1 device space
MCFG_DEVICE_ADD("type1", ADDRESS_MAP_BANK, 0)
MCFG_DEVICE_PROGRAM_MAP(type1space_map)
MCFG_ADDRESS_MAP_BANK_ENDIANNESS(ENDIANNESS_BIG)
MCFG_ADDRESS_MAP_BANK_DATABUS_WIDTH(32)
MCFG_ADDRESS_MAP_BANK_STRIDE(0x80000000)
MCFG_SCC8530_ADD(SCC1_TAG, XTAL_4_9152MHz, 0, 0, 0, 0)
MCFG_SCC8530_ADD(SCC2_TAG, XTAL_4_9152MHz, 0, 0, 0, 0)
MCFG_Z80SCC_OUT_TXDA_CB(DEVWRITELINE(RS232A_TAG, rs232_port_device, write_txd))
@ -926,11 +1024,11 @@ ROM_END
/* Driver */
/* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME FLAGS */
COMP( 198?, sun4_300, 0, 0, sun4, sun4, driver_device, 0, "Sun Microsystems", "Sun 4/3x0", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
COMP( 198?, sun4_40, sun4_300,0, sun4, sun4, driver_device, 0, "Sun Microsystems", "SPARCstation IPC (Sun 4/40)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
COMP( 198?, sun4_50, sun4_300,0, sun4, sun4, driver_device, 0, "Sun Microsystems", "SPARCstation IPX (Sun 4/50)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
COMP( 198?, sun4_20, sun4_300,0, sun4, sun4, driver_device, 0, "Sun Microsystems", "SPARCstation SLC (Sun 4/20)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
COMP( 198?, sun4_60, sun4_300,0, sun4, sun4, driver_device, 0, "Sun Microsystems", "SPARCstation 1 (Sun 4/60)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
COMP( 198?, sun4_75, sun4_300,0, sun4, sun4, driver_device, 0, "Sun Microsystems", "SPARCstation 2 (Sun 4/75)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
COMP( 198?, sun_s10, sun4_300,0, sun4, sun4, driver_device, 0, "Sun Microsystems", "SPARCstation 10 (Sun S10)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
COMP( 198?, sun_s20, sun4_300,0, sun4, sun4, driver_device, 0, "Sun Microsystems", "SPARCstation 20", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
COMP( 1987, sun4_300, 0, 0, sun4, sun4, driver_device, 0, "Sun Microsystems", "Sun 4/3x0", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
COMP( 1990, sun4_40, sun4_300,0, sun4, sun4, driver_device, 0, "Sun Microsystems", "SPARCstation IPC (Sun 4/40)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
COMP( 1991, sun4_50, sun4_300,0, sun4, sun4, driver_device, 0, "Sun Microsystems", "SPARCstation IPX (Sun 4/50)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
COMP( 199?, sun4_20, sun4_300,0, sun4, sun4, driver_device, 0, "Sun Microsystems", "SPARCstation SLC (Sun 4/20)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
COMP( 1989, sun4_60, sun4_300,0, sun4, sun4, driver_device, 0, "Sun Microsystems", "SPARCstation 1 (Sun 4/60)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
COMP( 1990, sun4_75, sun4_300,0, sun4, sun4, driver_device, 0, "Sun Microsystems", "SPARCstation 2 (Sun 4/75)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
COMP( 1992, sun_s10, sun4_300,0, sun4, sun4, driver_device, 0, "Sun Microsystems", "SPARCstation 10 (Sun S10)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
COMP( 1994, sun_s20, sun4_300,0, sun4, sun4, driver_device, 0, "Sun Microsystems", "SPARCstation 20", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)