mirror of
https://github.com/holub/mame
synced 2025-06-27 06:39:03 +03:00
sun4: checkpoint (nw)
This commit is contained in:
parent
2005b3ae3f
commit
7d4cfb098a
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user