diff --git a/src/mame/drivers/sun4.cpp b/src/mame/drivers/sun4.cpp index ceae4a5e568..ba95e54f0d8 100644 --- a/src/mame/drivers/sun4.cpp +++ b/src/mame/drivers/sun4.cpp @@ -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 m_maincpu; + required_device m_scc1; + required_device m_scc2; + optional_device m_type0space, m_type1space; + required_device m_ram; required_memory_region m_rom; - required_device m_kbdmouse; - required_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)