mirror of
https://github.com/holub/mame
synced 2025-06-06 21:03:47 +03:00
sun4 updates:
- Preliminary counter/timer support [R. Belmont] - Support both 8 and 16 context variants of sun4c arch [R. Belmont] - Added SPARCStation 1+ ROM [Al Kossow]
This commit is contained in:
parent
9f415edfe0
commit
81c3d47a6c
@ -390,7 +390,7 @@
|
||||
ffe80274: loop that goes wobbly and fails
|
||||
ffe80dc4: switch off boot mode, MMU maps ROM to copy in RAM from here on
|
||||
ffe82000: start of FORTH (?) interpreter once decompressed
|
||||
text in decmopressed area claims to be FORTH-83 FCode, but the opcodes
|
||||
text in decompressed area claims to be FORTH-83 FCode, but the opcodes
|
||||
do not match the documented OpenFirmware FCode ones at all.
|
||||
|
||||
****************************************************************************/
|
||||
@ -484,6 +484,10 @@ public:
|
||||
|
||||
virtual void machine_reset() override;
|
||||
virtual void machine_start() override;
|
||||
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
|
||||
|
||||
static const device_timer_id TIMER_0 = 0;
|
||||
static const device_timer_id TIMER_1 = 1;
|
||||
|
||||
DECLARE_READ32_MEMBER( sun4_mmu_r );
|
||||
DECLARE_WRITE32_MEMBER( sun4_mmu_w );
|
||||
@ -491,6 +495,13 @@ public:
|
||||
DECLARE_WRITE32_MEMBER( ram_w );
|
||||
DECLARE_READ32_MEMBER( ss1_sl0_id );
|
||||
DECLARE_READ32_MEMBER( ss1_sl3_id );
|
||||
DECLARE_READ32_MEMBER( timer_r );
|
||||
DECLARE_WRITE32_MEMBER( timer_w );
|
||||
DECLARE_READ8_MEMBER( irq_r );
|
||||
DECLARE_WRITE8_MEMBER( irq_w );
|
||||
|
||||
DECLARE_DRIVER_INIT(sun4c);
|
||||
DECLARE_DRIVER_INIT(ss2);
|
||||
|
||||
protected:
|
||||
required_device<mb86901_device> m_maincpu;
|
||||
@ -503,12 +514,18 @@ protected:
|
||||
UINT32 m_context;
|
||||
UINT8 m_system_enable;
|
||||
UINT32 m_buserror[4];
|
||||
UINT32 m_counter[4];
|
||||
|
||||
private:
|
||||
UINT32 *m_ram_ptr;
|
||||
UINT8 m_segmap[8][4096];
|
||||
UINT32 m_pagemap[8192];
|
||||
UINT8 m_segmap[16][4096];
|
||||
UINT32 m_pagemap[16384];
|
||||
UINT32 m_ram_size, m_ram_size_words;
|
||||
UINT8 m_ctx_mask; // SS2 is sun4c but has 16 contexts; most have 8
|
||||
UINT8 m_pmeg_mask; // SS2 is sun4c but has 16384 PTEs; most have 8192
|
||||
UINT8 m_irq_reg; // IRQ control
|
||||
|
||||
emu_timer *m_c0_timer, *m_c1_timer;
|
||||
|
||||
void l2p_command(int ref, int params, const char **param);
|
||||
};
|
||||
@ -533,6 +550,7 @@ READ32_MEMBER( sun4_state::sun4_mmu_r )
|
||||
switch (offset >> 26)
|
||||
{
|
||||
case 3: // context reg
|
||||
if (mem_mask == 0x00ff0000) return m_context<<16;
|
||||
return m_context<<24;
|
||||
|
||||
case 4: // system enable reg
|
||||
@ -554,8 +572,8 @@ READ32_MEMBER( sun4_state::sun4_mmu_r )
|
||||
//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;
|
||||
case 0: if (mem_mask == 0xff000000) return m_scc2->cb_r(space, offset)<<24; else return m_scc2->db_r(space, offset)<<8; break;
|
||||
case 1: if (mem_mask == 0xff000000) return m_scc2->ca_r(space, offset)<<24; else return m_scc2->da_r(space, offset)<<8; break;
|
||||
}
|
||||
return 0xffffffff;
|
||||
|
||||
@ -566,14 +584,14 @@ READ32_MEMBER( sun4_state::sun4_mmu_r )
|
||||
}
|
||||
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());
|
||||
//printf("sun4: read segment map @ %x (ctx %d entry %d, mem_mask %08x, PC=%x)\n", offset << 2, m_context & m_ctx_mask, (offset>>16) & 0xfff, mem_mask, m_maincpu->pc());
|
||||
if (mem_mask == 0xffff0000)
|
||||
{
|
||||
return m_segmap[m_context][(offset>>16) & 0xfff]<<16;
|
||||
return m_segmap[m_context & m_ctx_mask][(offset>>16) & 0xfff]<<16;
|
||||
}
|
||||
else if (mem_mask == 0xff000000)
|
||||
{
|
||||
return m_segmap[m_context][(offset>>16) & 0xfff]<<24;
|
||||
return m_segmap[m_context & m_ctx_mask][(offset>>16) & 0xfff]<<24;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -582,9 +600,9 @@ READ32_MEMBER( sun4_state::sun4_mmu_r )
|
||||
return 0x0;
|
||||
|
||||
case 4: // page map
|
||||
page = m_segmap[m_context & 7][(offset >> 16) & 0xfff] << 6;
|
||||
page = (m_segmap[m_context & m_ctx_mask][(offset >> 16) & 0xfff] & m_pmeg_mask) << 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());
|
||||
//printf("sun4: read page map @ %x (entry %d, seg %d, PMEG %d, mem_mask %08x, PC=%x)\n", offset << 2, page, (offset >> 16) & 0xfff, m_segmap[m_context & m_ctx_mask][(offset >> 16) & 0xfff] & m_pmeg_mask, mem_mask, m_maincpu->pc());
|
||||
return m_pagemap[page];
|
||||
break;
|
||||
|
||||
@ -594,7 +612,7 @@ READ32_MEMBER( sun4_state::sun4_mmu_r )
|
||||
case 11:
|
||||
{
|
||||
// it's translation time
|
||||
UINT8 pmeg = m_segmap[m_context & 7][(offset >> 16) & 0xfff];
|
||||
UINT8 pmeg = m_segmap[m_context & m_ctx_mask][(offset >> 16) & 0xfff] & m_pmeg_mask;
|
||||
UINT32 entry = (pmeg << 6) + ((offset >> 10) & 0x3f);
|
||||
|
||||
if (m_pagemap[entry] & PM_VALID)
|
||||
@ -668,6 +686,7 @@ WRITE32_MEMBER( sun4_state::sun4_mmu_w )
|
||||
|
||||
case 4: // system enable reg
|
||||
m_system_enable = data>>24;
|
||||
printf("%08x to system enable, mask %08x\n", data, mem_mask);
|
||||
return;
|
||||
|
||||
case 8: // cache tags
|
||||
@ -679,11 +698,11 @@ WRITE32_MEMBER( sun4_state::sun4_mmu_w )
|
||||
return;
|
||||
|
||||
case 0xf: // UART bypass
|
||||
//printf("%08x to UART @ %d, mask %08x\n", data, offset & 3, mem_mask);
|
||||
//printf("%08x to UART bypass @ %x, mask %08x\n", data, offset<<2, 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;
|
||||
case 0: if (mem_mask == 0xff000000) m_scc2->cb_w(space, offset, data>>24); else m_scc2->db_w(space, offset, data>>8); break;
|
||||
case 1: if (mem_mask == 0xff000000) m_scc2->ca_w(space, offset, data>>24); else { m_scc2->da_w(space, offset, data>>8); printf("%c", data>>8); } break;
|
||||
}
|
||||
return;
|
||||
|
||||
@ -697,17 +716,17 @@ WRITE32_MEMBER( sun4_state::sun4_mmu_w )
|
||||
{
|
||||
UINT8 segdata = 0;
|
||||
//printf("segment write, mask %08x, PC=%x\n", mem_mask, m_maincpu->pc());
|
||||
if (mem_mask == 0xffff0000) segdata = (data >> 16) & 0x7f;
|
||||
else if (mem_mask == 0xff000000) segdata = (data >> 24) & 0x7f;
|
||||
if (mem_mask == 0xffff0000) segdata = (data >> 16) & 0xff;
|
||||
else if (mem_mask == 0xff000000) segdata = (data >> 24) & 0xff;
|
||||
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
|
||||
//printf("sun4: %08x to segment map @ %x (ctx %d entry %d, mem_mask %08x, PC=%x)\n", segdata, offset << 2, m_context, (offset>>16) & 0xfff, mem_mask, m_maincpu->pc());
|
||||
m_segmap[m_context & m_ctx_mask][(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 = (m_segmap[m_context & m_ctx_mask][(offset >> 16) & 0xfff] & m_pmeg_mask) << 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]);
|
||||
@ -718,7 +737,7 @@ WRITE32_MEMBER( sun4_state::sun4_mmu_w )
|
||||
case 10:
|
||||
case 11:
|
||||
// it's translation time
|
||||
UINT8 pmeg = m_segmap[m_context & 7][(offset >> 16) & 0xfff];
|
||||
UINT8 pmeg = m_segmap[m_context & 7][(offset >> 16) & 0xfff] & m_pmeg_mask;
|
||||
UINT32 entry = (pmeg << 6) + ((offset >> 10) & 0x3f);
|
||||
|
||||
if (m_pagemap[entry] & PM_VALID)
|
||||
@ -797,6 +816,8 @@ void sun4_state::machine_reset()
|
||||
{
|
||||
m_context = 0;
|
||||
m_system_enable = 0;
|
||||
m_irq_reg = 0;
|
||||
memset(m_counter, 0, sizeof(m_counter));
|
||||
}
|
||||
|
||||
void sun4_state::machine_start()
|
||||
@ -811,6 +832,12 @@ void sun4_state::machine_start()
|
||||
using namespace std::placeholders;
|
||||
machine().debugger().console().register_command("l2p", CMDFLAG_NONE, 0, 1, 1, std::bind(&sun4_state::l2p_command, this, _1, _2, _3));
|
||||
}
|
||||
|
||||
// allocate timers for the built-in two channel timer
|
||||
m_c0_timer = timer_alloc(TIMER_0);
|
||||
m_c1_timer = timer_alloc(TIMER_1);
|
||||
m_c0_timer->adjust(attotime::never);
|
||||
m_c1_timer->adjust(attotime::never);
|
||||
}
|
||||
|
||||
READ32_MEMBER( sun4_state::ram_r )
|
||||
@ -896,11 +923,80 @@ 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(0x03000000, 0x0300000f) AM_READWRITE(timer_r, timer_w)
|
||||
AM_RANGE(0x05000000, 0x05000003) AM_READWRITE8(irq_r, irq_w, 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
|
||||
|
||||
READ8_MEMBER( sun4_state::irq_r )
|
||||
{
|
||||
return m_irq_reg;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER( sun4_state::irq_w )
|
||||
{
|
||||
printf("%02x to IRQ\n", data);
|
||||
|
||||
m_irq_reg = data;
|
||||
}
|
||||
|
||||
void sun4_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case TIMER_0:
|
||||
printf("Timer 0 expired\n");
|
||||
m_counter[0] = 0x80000000 | (1 << 10);
|
||||
m_counter[1] |= 0x80000000;
|
||||
m_c0_timer->adjust(attotime::never);
|
||||
if ((m_irq_reg & 0x21) == 0x21)
|
||||
{
|
||||
//m_maincpu->trap(SPARC_INT10);
|
||||
printf("Taking INT10\n");
|
||||
}
|
||||
break;
|
||||
|
||||
case TIMER_1:
|
||||
m_counter[2] = 0x80000000 | (1 << 10);
|
||||
m_counter[3] |= 0x80000000;
|
||||
m_c0_timer->adjust(attotime::never);
|
||||
if ((m_irq_reg & 0x81) == 0x81)
|
||||
{
|
||||
//m_maincpu->trap(SPARC_INT14);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
READ32_MEMBER( sun4_state::timer_r )
|
||||
{
|
||||
printf("Read timer @ %x, mask %08x\n", offset, mem_mask);
|
||||
return m_counter[offset];
|
||||
}
|
||||
|
||||
WRITE32_MEMBER( sun4_state::timer_w )
|
||||
{
|
||||
printf("%08x to timer @ %x, mask %08x\n", data, offset<<2, mem_mask);
|
||||
COMBINE_DATA(&m_counter[offset]);
|
||||
|
||||
// writing limit 0?
|
||||
if (offset == 1)
|
||||
{
|
||||
int period = (m_counter[1] >> 10) & 0x1fffff;
|
||||
printf("Setting limit 1 period to %d us\n", period);
|
||||
m_c0_timer->adjust(attotime::from_usec(period));
|
||||
}
|
||||
|
||||
// writing limit 1?
|
||||
if (offset == 3)
|
||||
{
|
||||
int period = (m_counter[3] >> 10) & 0x1fffff;
|
||||
m_c1_timer->adjust(attotime::from_usec(period));
|
||||
}
|
||||
}
|
||||
|
||||
// indicate 4/60 SCSI/DMA/Ethernet card exists
|
||||
READ32_MEMBER( sun4_state::ss1_sl0_id )
|
||||
{
|
||||
@ -1094,6 +1190,12 @@ ROM_START( sun4_60 )
|
||||
ROM_LOAD( "ss1v29.rom", 0x0000, 0x20000, CRC(e3f103a9) SHA1(5e95835f1090ea94859bd005757f0e7b5e86181b))
|
||||
ROM_END
|
||||
|
||||
// SPARCstation 1+ (Sun 4/65)
|
||||
ROM_START( sun4_65 )
|
||||
ROM_REGION32_BE( 0x80000, "user1", ROMREGION_ERASEFF )
|
||||
ROM_LOAD( "525-1108-05_1.3_ver_4.bin", 0x000000, 0x020000, CRC(67f1b3e2) SHA1(276ec5ca1dcbdfa202120560f55d52036720f87d) )
|
||||
ROM_END
|
||||
|
||||
// SPARCstation 2 (Sun 4/75)
|
||||
ROM_START( sun4_75 )
|
||||
ROM_REGION32_BE( 0x80000, "user1", ROMREGION_ERASEFF )
|
||||
@ -1120,14 +1222,32 @@ ROM_START( sun_s20 )
|
||||
ROMX_LOAD( "ss10-20_v2.25r.rom", 0x0000, 0x80000, CRC(105ba132) SHA1(58530e88369d1d26ab11475c7884205f2299d255), ROM_BIOS(2))
|
||||
ROM_END
|
||||
|
||||
DRIVER_INIT_MEMBER(sun4_state, sun4c)
|
||||
{
|
||||
m_ctx_mask = 0x7;
|
||||
m_pmeg_mask = 0x7f;
|
||||
}
|
||||
|
||||
DRIVER_INIT_MEMBER(sun4_state, ss2)
|
||||
{
|
||||
m_ctx_mask = 0xf;
|
||||
m_pmeg_mask = 0xff;
|
||||
}
|
||||
|
||||
/* Driver */
|
||||
|
||||
/* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME FLAGS */
|
||||
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)
|
||||
// sun4
|
||||
COMP( 1987, sun4_300, 0, 0, sun4, sun4, sun4_state, sun4c, "Sun Microsystems", "Sun 4/3x0", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
|
||||
|
||||
// sun4c
|
||||
COMP( 1990, sun4_40, sun4_300,0, sun4, sun4, sun4_state, sun4c, "Sun Microsystems", "SPARCstation IPC (Sun 4/40)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
|
||||
COMP( 1991, sun4_50, sun4_300,0, sun4, sun4, sun4_state, sun4c, "Sun Microsystems", "SPARCstation IPX (Sun 4/50)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
|
||||
COMP( 199?, sun4_20, sun4_300,0, sun4, sun4, sun4_state, sun4c, "Sun Microsystems", "SPARCstation SLC (Sun 4/20)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
|
||||
COMP( 1989, sun4_60, sun4_300,0, sun4, sun4, sun4_state, sun4c, "Sun Microsystems", "SPARCstation 1 (Sun 4/60)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
|
||||
COMP( 1990, sun4_65, sun4_300,0, sun4, sun4, sun4_state, sun4c, "Sun Microsystems", "SPARCstation 1+ (Sun 4/65)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
|
||||
COMP( 1990, sun4_75, sun4_300,0, sun4, sun4, sun4_state, ss2, "Sun Microsystems", "SPARCstation 2 (Sun 4/75)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
|
||||
|
||||
// sun4m
|
||||
COMP( 1992, sun_s10, sun4_300,0, sun4, sun4, sun4_state, sun4c, "Sun Microsystems", "SPARCstation 10 (Sun S10)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
|
||||
COMP( 1994, sun_s20, sun4_300,0, sun4, sun4, sun4_state, sun4c, "Sun Microsystems", "SPARCstation 20", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
|
||||
|
@ -34045,6 +34045,7 @@ sun4_300 //
|
||||
sun4_40 //
|
||||
sun4_50 //
|
||||
sun4_60 //
|
||||
sun4_65 //
|
||||
sun4_75 //
|
||||
|
||||
@source:suna16.cpp
|
||||
|
Loading…
Reference in New Issue
Block a user