mirror of
https://github.com/holub/mame
synced 2025-06-29 23:48:56 +03:00
sgi: ip6, ip12, ip12 refactor and wip
* added int2 and pic1 devices * refactor hpc1 device, add ethernet support * refactor 4dpi into ip6 and ip12 variants * refactor indigo into ip12 and ip20 variants * rework 4dpi3x based on hpc1, int2 and pic1 * ip6 and ip12 mostly working (will run irix 4.0.5 and 5.3 except for graphics issues and missing audio)
This commit is contained in:
parent
fbc8d7178c
commit
30b3c5010a
@ -40718,25 +40718,28 @@ tim011 //
|
||||
@source:sfrj/tim100.cpp
|
||||
tim100 //
|
||||
|
||||
@source:sgi/4dpi.cpp
|
||||
4d20 // IP6: Personal Iris 4D/20, R2000 @12.5MHz
|
||||
4d25 // IP10: Personal Iris 4D/25, R3000 @20MHz
|
||||
4d30 // IP14: Personal Iris 4D/30, R3000A @30MHz
|
||||
4d35 // IP12: Personal Iris 4D/35, R3000A @36MHz
|
||||
|
||||
@source:sgi/crimson.cpp
|
||||
crimson // (c) 1992 SGI
|
||||
|
||||
@source:sgi/indigo.cpp
|
||||
indigo3k // IP12: Indigo 1, R3000, 33MHz
|
||||
indigo4k // IP20: Indigo 1, R4400, 150MHz
|
||||
|
||||
@source:sgi/indy_indigo2.cpp
|
||||
indy_4610 // IP22: Indy, R4600, 100MHz
|
||||
indy_4613 // IP22: Indy, R4600, 133MHz
|
||||
indy_5015 // IP22: Indy, R5000, 150MHz
|
||||
indigo2_4415 // IP24: Indigo 2, R4400, 150MHz
|
||||
|
||||
@source:sgi/ip6.cpp
|
||||
pi4d20 // Personal IRIS 4D/20 (R2000 @ 12.5MHz)
|
||||
pi4d25 // Personal IRIS 4D/25 (R3000 @ 20MHz)
|
||||
|
||||
@source:sgi/ip12.cpp
|
||||
pi4d30 // Personal IRIS 4D/30 (R3000A @ 30MHz)
|
||||
pi4d35 // Personal IRIS 4D/35 (R3000A @ 36MHz)
|
||||
indigo // IRIS Indigo HP1 (R3000A @ 33MHz)
|
||||
|
||||
@source:sgi/ip20.cpp
|
||||
indigo_r4000 // Indigo HP2, PM1 (R4000 @ 100MHz)
|
||||
indigo_r4400 // Indigo HP2, PM2 (R4400 @ 150MHz)
|
||||
|
||||
@source:sgi/iris3130.cpp
|
||||
iris3130 // IP2: IRIS 3xx0, 68020, 16MHz
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -11,129 +11,131 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "machine/dp8573a.h"
|
||||
#include "machine/eepromser.h"
|
||||
#include "machine/pit8253.h"
|
||||
#include "machine/wd33c9x.h"
|
||||
#include "machine/z80scc.h"
|
||||
#include "machine/edlc.h"
|
||||
|
||||
class hpc1_device : public device_t
|
||||
class hpc1_device
|
||||
: public device_t
|
||||
, public device_memory_interface
|
||||
{
|
||||
public:
|
||||
template <typename T, typename U>
|
||||
hpc1_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&cpu_tag, U &&eeprom_tag)
|
||||
: hpc1_device(mconfig, tag, owner, (uint32_t)0)
|
||||
{
|
||||
m_maincpu.set_tag(std::forward<T>(cpu_tag));
|
||||
m_eeprom.set_tag(std::forward<U>(eeprom_tag));
|
||||
}
|
||||
hpc1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
|
||||
|
||||
hpc1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
template <typename T> void set_gio(T &&tag, int spacenum) { m_gio.set_tag(std::forward<T>(tag), spacenum); }
|
||||
template <typename T> void set_enet(T &&tag) { m_enet.set_tag(std::forward<T>(tag)); }
|
||||
|
||||
uint32_t read(offs_t offset, uint32_t mem_mask = ~0);
|
||||
void write(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
|
||||
auto int_w() { return m_int_w.bind(); }
|
||||
template <unsigned N> auto dma_r_cb() { return m_dma_r[N].bind(); }
|
||||
template <unsigned N> auto dma_w_cb() { return m_dma_w[N].bind(); }
|
||||
auto eeprom_dati() { return m_eeprom_dati.bind(); }
|
||||
auto eeprom_out() { return m_eeprom_out.bind(); }
|
||||
|
||||
template <unsigned N> void write_drq(int state);
|
||||
void write_int(int state);
|
||||
|
||||
void map(address_map &map);
|
||||
|
||||
protected:
|
||||
// device_t implementation
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
virtual void device_add_mconfig(machine_config &config) override;
|
||||
|
||||
void scsi_irq(int state);
|
||||
void scsi_drq(int state);
|
||||
// device_memory_interface implementation
|
||||
virtual space_config_vector memory_space_config() const override;
|
||||
|
||||
void set_timer_int_clear(uint32_t data);
|
||||
void timer0_int(int state);
|
||||
void timer1_int(int state);
|
||||
void timer2_int(int state);
|
||||
void duart0_int_w(int state);
|
||||
void duart1_int_w(int state);
|
||||
void duart2_int_w(int state);
|
||||
// dma
|
||||
void enet_dma();
|
||||
void scsi_dma();
|
||||
void scsi_chain();
|
||||
|
||||
void duart_int_w(int channel, int status);
|
||||
void raise_local_irq(int channel, uint8_t source_mask);
|
||||
void lower_local_irq(int channel, uint8_t source_mask);
|
||||
void update_irq(int channel);
|
||||
// ethernet read handlers
|
||||
u32 cxbp_r() { return m_enet_cxbp; }
|
||||
u32 nxbdp_r() { return m_enet_nxbdp; }
|
||||
u32 xbc_r() { return m_enet_xbc; }
|
||||
u32 cxbdp_r() { return m_enet_cxbdp; }
|
||||
u32 cpfxbdp_r() { return m_enet_cpfxbdp; }
|
||||
u32 ppfxbdp_r() { return m_enet_ppfxbdp; }
|
||||
u32 intdelay_r() { return m_enet_intdelay; }
|
||||
u32 trstat_r();
|
||||
u32 rcvstat_r();
|
||||
u32 ctl_r() { return m_enet_ctrl; }
|
||||
u32 rbc_r() { return m_enet_rbc; }
|
||||
u32 crbp_r() { return m_enet_crbp; }
|
||||
u32 nrbdp_r() { return m_enet_nrbdp; }
|
||||
u32 crbdp_r() { return m_enet_crbdp; }
|
||||
|
||||
void do_scsi_dma();
|
||||
// ethernet write handlers
|
||||
void cxbp_w(u32 data);
|
||||
void nxbdp_w(u32 data);
|
||||
void xbc_w(u32 data);
|
||||
void cxbdp_w(u32 data);
|
||||
void cpfxbdp_w(u32 data);
|
||||
void ppfxbdp_w(u32 data);
|
||||
void intdelay_w(u32 data);
|
||||
void trstat_w(u32 data);
|
||||
void rcvstat_w(u32 data);
|
||||
void ctl_w(u32 data);
|
||||
void rbc_w(u32 data);
|
||||
void crbp_w(u32 data);
|
||||
void nrbdp_w(u32 data);
|
||||
void crbdp_w(u32 data);
|
||||
|
||||
void dump_chain(uint32_t base);
|
||||
void fetch_chain();
|
||||
void decrement_chain();
|
||||
// scsi read handlers
|
||||
u32 scsi_bc_r() { return m_scsi_bc; }
|
||||
u32 scsi_cbp_r() { return m_scsi_cbp; }
|
||||
u32 scsi_nbdp_r() { return m_scsi_nbdp; }
|
||||
u32 scsi_ctrl_r() { return m_scsi_ctrl; }
|
||||
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<eeprom_serial_93cxx_device> m_eeprom;
|
||||
required_device<wd33c93_device> m_wd33c93;
|
||||
required_device_array<scc85c30_device, 3> m_scc;
|
||||
required_device<pit8254_device> m_pit;
|
||||
required_device<dp8572a_device> m_rtc;
|
||||
// scsi write handlers
|
||||
void scsi_bc_w(u32 data) { m_scsi_bc = data & 0x1fffU; }
|
||||
void scsi_cbp_w(u32 data) { m_scsi_cbp = data & 0x8fff'ffffU; }
|
||||
void scsi_nbdp_w(u32 data);
|
||||
void scsi_ctrl_w(u32 data);
|
||||
|
||||
enum
|
||||
{
|
||||
LOCAL0_FIFO_GIO0 = 0x01,
|
||||
LOCAL0_PARALLEL = 0x02,
|
||||
LOCAL0_SCSI = 0x04,
|
||||
LOCAL0_ETHERNET = 0x08,
|
||||
LOCAL0_GFX_DMA = 0x10,
|
||||
LOCAL0_DUART = 0x20,
|
||||
LOCAL0_GIO1 = 0x40,
|
||||
LOCAL0_VME0 = 0x80,
|
||||
u16 dsp_bc_r() { return m_dsp_bc; }
|
||||
void dsp_bc_w(u16 data) { m_dsp_bc = data; }
|
||||
|
||||
LOCAL1_GR1_CASE = 0x02,
|
||||
LOCAL1_VME1 = 0x08,
|
||||
LOCAL1_DSP = 0x10,
|
||||
LOCAL1_ACFAIL = 0x20,
|
||||
LOCAL1_VIDEO = 0x40,
|
||||
LOCAL1_RETRACE_GIO2 = 0x80
|
||||
};
|
||||
u8 aux_r();
|
||||
void aux_w(u8 data);
|
||||
|
||||
enum
|
||||
{
|
||||
HPC_DMACTRL_RESET = 0x01,
|
||||
HPC_DMACTRL_FLUSH = 0x02,
|
||||
HPC_DMACTRL_TO_MEM = 0x10,
|
||||
HPC_DMACTRL_ENABLE = 0x80
|
||||
};
|
||||
void pbus_map(address_map &map);
|
||||
|
||||
struct scsi_dma_t
|
||||
{
|
||||
uint32_t m_desc = 0;
|
||||
uint32_t m_addr = 0;
|
||||
uint32_t m_ctrl = 0;
|
||||
uint32_t m_length = 0;
|
||||
uint32_t m_next = 0;
|
||||
bool m_irq = false;
|
||||
bool m_drq = false;
|
||||
bool m_to_mem = false;
|
||||
bool m_active = false;
|
||||
};
|
||||
private:
|
||||
address_space_config const m_pbus;
|
||||
required_address_space m_gio;
|
||||
|
||||
static void cdrom_config(device_t *device);
|
||||
static void scsi_devices(device_slot_interface &device);
|
||||
static void indigo_mice(device_slot_interface &device);
|
||||
void wd33c93(device_t *device);
|
||||
optional_device<seeq8003_device> m_enet;
|
||||
|
||||
uint8_t m_misc_status = 0;
|
||||
uint32_t m_cpu_aux_ctrl = 0;
|
||||
uint32_t m_parbuf_ptr = 0;
|
||||
uint32_t m_local_int_status[2]{};
|
||||
uint32_t m_local_int_mask[2]{};
|
||||
bool m_int_status[2]{};
|
||||
uint32_t m_vme_int_mask[2]{};
|
||||
devcb_write_line m_int_w;
|
||||
devcb_read_line m_eeprom_dati;
|
||||
devcb_read8::array<2> m_dma_r;
|
||||
devcb_write8::array<2> m_dma_w;
|
||||
devcb_write8 m_eeprom_out;
|
||||
|
||||
scsi_dma_t m_scsi_dma;
|
||||
u8 m_drq;
|
||||
|
||||
uint8_t m_duart_int_status = 0;
|
||||
u32 m_enet_cxbp; // enet current transmit buffer pointer
|
||||
u32 m_enet_nxbdp; // enet current transmit buffer descriptor pointer
|
||||
u32 m_enet_xbc; // enet transmit byte count
|
||||
u32 m_enet_cxbdp; // enet current transmit buffer descriptor pointer
|
||||
u32 m_enet_cpfxbdp; // enet current packet first transmit buffer descriptor pointer
|
||||
u32 m_enet_ppfxbdp; // enet previous packet first transmit buffer descriptor pointer
|
||||
u32 m_enet_intdelay; // enet interrupt delay count
|
||||
u32 m_enet_txs; // enet transmit status
|
||||
u32 m_enet_rxs; // enet receive status
|
||||
u32 m_enet_ctrl; // enet interrupt, channel reset, buffer overflow
|
||||
u32 m_enet_rbc; // enet receive byte count
|
||||
u32 m_enet_crbp; // enet current receive buffer pointer
|
||||
u32 m_enet_nrbdp; // enet next receive buffer desriptor pointer
|
||||
u32 m_enet_crbdp; // enet current receive buffer descriptor pointer
|
||||
|
||||
address_space *m_cpu_space = nullptr;
|
||||
u32 m_scsi_bc; // scsi byte count
|
||||
u32 m_scsi_cbp; // scsi current buffer pointer
|
||||
u32 m_scsi_nbdp; // scsi next buffer descriptor pointer
|
||||
u32 m_scsi_ctrl; // scsi control
|
||||
|
||||
static char const *const RS232A_TAG;
|
||||
static char const *const RS232B_TAG;
|
||||
u16 m_dsp_bc;
|
||||
|
||||
static const XTAL SCC_PCLK;
|
||||
static const XTAL SCC_RXA_CLK;
|
||||
static const XTAL SCC_TXA_CLK;
|
||||
static const XTAL SCC_RXB_CLK;
|
||||
static const XTAL SCC_TXB_CLK;
|
||||
u8 m_aux;
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(SGI_HPC1, hpc1_device)
|
||||
|
@ -1,230 +0,0 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Ryan Holtz
|
||||
/*********************************************************************
|
||||
|
||||
SGI Indigo workstation
|
||||
|
||||
To-Do:
|
||||
- IP12 (R3000):
|
||||
* Everything
|
||||
- IP20 (R4000):
|
||||
* Figure out why the keyboard/mouse diagnostic fails
|
||||
* Work out a proper RAM mapping, or why the installer bails due
|
||||
to trying to access virtual address ffffa02c:
|
||||
88002584: lw $sp,-$5fd4($0)
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
//#include "cpu/dsp56156/dsp56156.h"
|
||||
#include "cpu/mips/mips1.h"
|
||||
#include "cpu/mips/r4000.h"
|
||||
#include "machine/eepromser.h"
|
||||
|
||||
#include "hpc1.h"
|
||||
#include "mc.h"
|
||||
#include "light.h"
|
||||
|
||||
#define LOG_UNKNOWN (1U << 1)
|
||||
#define LOG_INT (1U << 2)
|
||||
#define LOG_DSP (1U << 3)
|
||||
#define LOG_ALL (LOG_UNKNOWN | LOG_INT | LOG_DSP)
|
||||
|
||||
#define VERBOSE (LOG_UNKNOWN)
|
||||
#include "logmacro.h"
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
class indigo_state : public driver_device
|
||||
{
|
||||
public:
|
||||
indigo_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: driver_device(mconfig, type, tag)
|
||||
, m_hpc(*this, "hpc")
|
||||
, m_eeprom(*this, "eeprom")
|
||||
, m_gfx(*this, "lg1")
|
||||
{
|
||||
}
|
||||
|
||||
void indigo_base(machine_config &config);
|
||||
|
||||
protected:
|
||||
virtual void machine_start() override;
|
||||
virtual void machine_reset() override;
|
||||
|
||||
uint32_t int_r(offs_t offset, uint32_t mem_mask = ~0);
|
||||
void int_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
|
||||
uint32_t dsp_ram_r(offs_t offset, uint32_t mem_mask = ~0);
|
||||
void dsp_ram_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
|
||||
|
||||
void indigo_map(address_map &map);
|
||||
|
||||
required_device<hpc1_device> m_hpc;
|
||||
required_device<eeprom_serial_93cxx_device> m_eeprom;
|
||||
std::unique_ptr<uint32_t[]> m_dsp_ram;
|
||||
required_device<sgi_lg1_device> m_gfx;
|
||||
address_space *m_space = nullptr;
|
||||
};
|
||||
|
||||
class indigo3k_state : public indigo_state
|
||||
{
|
||||
public:
|
||||
indigo3k_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: indigo_state(mconfig, type, tag)
|
||||
, m_maincpu(*this, "maincpu")
|
||||
{
|
||||
}
|
||||
|
||||
void indigo3k(machine_config &config);
|
||||
|
||||
protected:
|
||||
void mem_map(address_map &map);
|
||||
|
||||
required_device<r3000a_device> m_maincpu;
|
||||
};
|
||||
|
||||
class indigo4k_state : public indigo_state
|
||||
{
|
||||
public:
|
||||
indigo4k_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: indigo_state(mconfig, type, tag)
|
||||
, m_maincpu(*this, "maincpu")
|
||||
, m_mem_ctrl(*this, "memctrl")
|
||||
{
|
||||
}
|
||||
|
||||
void indigo4k(machine_config &config);
|
||||
|
||||
protected:
|
||||
virtual void machine_reset() override;
|
||||
|
||||
void mem_map(address_map &map);
|
||||
|
||||
required_device<r4000_device> m_maincpu;
|
||||
required_device<sgi_mc_device> m_mem_ctrl;
|
||||
};
|
||||
|
||||
void indigo_state::machine_start()
|
||||
{
|
||||
m_dsp_ram = std::make_unique<uint32_t[]>(0x8000);
|
||||
save_pointer(NAME(&m_dsp_ram[0]), 0x8000);
|
||||
}
|
||||
|
||||
void indigo_state::machine_reset()
|
||||
{
|
||||
}
|
||||
|
||||
void indigo4k_state::machine_reset()
|
||||
{
|
||||
indigo_state::machine_reset();
|
||||
}
|
||||
|
||||
uint32_t indigo_state::int_r(offs_t offset, uint32_t mem_mask)
|
||||
{
|
||||
LOGMASKED(LOG_INT, "%s: INT Read: %08x & %08x\n", machine().describe_context(), 0x1fbd9000 + offset*4, mem_mask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void indigo_state::int_w(offs_t offset, uint32_t data, uint32_t mem_mask)
|
||||
{
|
||||
LOGMASKED(LOG_INT, "%s: INT Write: %08x = %08x & %08x\n", machine().describe_context(), 0x1fbd9000 + offset*4, data, mem_mask);
|
||||
}
|
||||
|
||||
uint32_t indigo_state::dsp_ram_r(offs_t offset, uint32_t mem_mask)
|
||||
{
|
||||
LOGMASKED(LOG_DSP, "%s: DSP RAM Read: %08x = %08x & %08x\n", machine().describe_context(), 0x1fbe0000 + offset*4, m_dsp_ram[offset], mem_mask);
|
||||
return m_dsp_ram[offset];
|
||||
}
|
||||
|
||||
void indigo_state::dsp_ram_w(offs_t offset, uint32_t data, uint32_t mem_mask)
|
||||
{
|
||||
LOGMASKED(LOG_DSP, "%s: DSP RAM Write: %08x = %08x & %08x\n", machine().describe_context(), 0x1fbe0000 + offset*4, data, mem_mask);
|
||||
m_dsp_ram[offset] = data;
|
||||
}
|
||||
|
||||
|
||||
void indigo_state::indigo_map(address_map &map)
|
||||
{
|
||||
map(0x1f3f0000, 0x1f3f7fff).m(m_gfx, FUNC(sgi_lg1_device::map));
|
||||
map(0x1fb80000, 0x1fb8ffff).rw(m_hpc, FUNC(hpc1_device::read), FUNC(hpc1_device::write));
|
||||
map(0x1fbd9000, 0x1fbd903f).rw(FUNC(indigo_state::int_r), FUNC(indigo_state::int_w));
|
||||
map(0x1fbe0000, 0x1fbfffff).rw(FUNC(indigo_state::dsp_ram_r), FUNC(indigo_state::dsp_ram_w));
|
||||
}
|
||||
|
||||
void indigo3k_state::mem_map(address_map &map)
|
||||
{
|
||||
indigo_map(map);
|
||||
map(0x1fc00000, 0x1fc3ffff).rom().region("user1", 0);
|
||||
}
|
||||
|
||||
void indigo4k_state::mem_map(address_map &map)
|
||||
{
|
||||
indigo_map(map);
|
||||
map(0x1fa00000, 0x1fa1ffff).rw(m_mem_ctrl, FUNC(sgi_mc_device::read), FUNC(sgi_mc_device::write));
|
||||
map(0x1fc00000, 0x1fc7ffff).rom().region("user1", 0);
|
||||
}
|
||||
|
||||
static INPUT_PORTS_START(indigo)
|
||||
INPUT_PORTS_END
|
||||
|
||||
void indigo_state::indigo_base(machine_config &config)
|
||||
{
|
||||
SGI_LG1(config, m_gfx);
|
||||
|
||||
EEPROM_93C56_16BIT(config, m_eeprom);
|
||||
}
|
||||
|
||||
void indigo3k_state::indigo3k(machine_config &config)
|
||||
{
|
||||
indigo_base(config);
|
||||
|
||||
R3000A(config, m_maincpu, 33.333_MHz_XTAL, 32768, 32768);
|
||||
downcast<r3000a_device &>(*m_maincpu).set_endianness(ENDIANNESS_BIG);
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &indigo3k_state::mem_map);
|
||||
|
||||
SGI_HPC1(config, m_hpc, m_maincpu, m_eeprom);
|
||||
}
|
||||
|
||||
static DEVICE_INPUT_DEFAULTS_START(ip20_mc)
|
||||
DEVICE_INPUT_DEFAULTS("VALID", 0x0f, 0x07)
|
||||
DEVICE_INPUT_DEFAULTS_END
|
||||
|
||||
void indigo4k_state::indigo4k(machine_config &config)
|
||||
{
|
||||
indigo_base(config);
|
||||
|
||||
R4000(config, m_maincpu, 50000000);
|
||||
//m_maincpu->set_icache_size(32768);
|
||||
//m_maincpu->set_dcache_size(32768);
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &indigo4k_state::mem_map);
|
||||
|
||||
SGI_MC(config, m_mem_ctrl, m_maincpu, m_eeprom, 50000000);
|
||||
m_mem_ctrl->eisa_present().set_constant(0);
|
||||
m_mem_ctrl->set_input_default(DEVICE_INPUT_DEFAULTS_NAME(ip20_mc));
|
||||
|
||||
SGI_HPC1(config, m_hpc, m_maincpu, m_eeprom);
|
||||
}
|
||||
|
||||
ROM_START( indigo3k )
|
||||
ROM_REGION32_BE( 0x40000, "user1", 0 )
|
||||
ROM_SYSTEM_BIOS( 0, "401-rev-c", "SGI Version 4.0.1 Rev C LG1/GR2, Jul 9, 1992" ) // dumped over serial connection from boot monitor and swapped
|
||||
ROMX_LOAD( "ip12prom.070-8088-xxx.u56", 0x000000, 0x040000, CRC(25ca912f) SHA1(94b3753d659bfe50b914445cef41290122f43880), ROM_GROUPWORD | ROM_REVERSE | ROM_BIOS(0) )
|
||||
ROM_SYSTEM_BIOS( 1, "401-rev-d", "SGI Version 4.0.1 Rev D LG1/GR2, Mar 24, 1992" ) // dumped with EPROM programmer
|
||||
ROMX_LOAD( "ip12prom.070-8088-002.u56", 0x000000, 0x040000, CRC(ea4329ef) SHA1(b7d67d0e30ae8836892f7170dd4757732a0a3fd6), ROM_GROUPWORD | ROM_REVERSE | ROM_BIOS(1) )
|
||||
ROM_END
|
||||
|
||||
ROM_START( indigo4k )
|
||||
ROM_REGION64_BE( 0x80000, "user1", 0 )
|
||||
ROM_SYSTEM_BIOS( 0, "405d-rev-a", "SGI Version 4.0.5D Rev A IP20, Aug 19, 1992" )
|
||||
ROMX_LOAD( "ip20prom.070-8116-004.bin", 0x000000, 0x080000, CRC(940d960e) SHA1(596aba530b53a147985ff3f6f853471ce48c866c), ROM_GROUPDWORD | ROM_REVERSE | ROM_BIOS(0) )
|
||||
ROM_SYSTEM_BIOS( 1, "405g-rev-b", "SGI Version 4.0.5G Rev B IP20, Nov 10, 1992" ) // dumped over serial connection from boot monitor and swapped
|
||||
ROMX_LOAD( "ip20prom.070-8116-005.bin", 0x000000, 0x080000, CRC(1875b645) SHA1(52f5d7baea3d1bc720eb2164104c177e23504345), ROM_GROUPDWORD | ROM_REVERSE | ROM_BIOS(1) )
|
||||
ROM_END
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
|
||||
COMP( 1991, indigo3k, 0, 0, indigo3k, indigo, indigo3k_state, empty_init, "Silicon Graphics Inc", "IRIS Indigo (R3000, 33MHz)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND )
|
||||
COMP( 1993, indigo4k, 0, 0, indigo4k, indigo, indigo4k_state, empty_init, "Silicon Graphics Inc", "IRIS Indigo (R4400, 150MHz)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND )
|
214
src/mame/sgi/int2.cpp
Normal file
214
src/mame/sgi/int2.cpp
Normal file
@ -0,0 +1,214 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Patrick Mackinlay
|
||||
|
||||
/*
|
||||
* Silicon Graphics Local I/O Interrupt Multiplexor (INT2).
|
||||
*
|
||||
* TODO:
|
||||
* - bus error
|
||||
* - fpu interrupt
|
||||
*/
|
||||
|
||||
/*
|
||||
* # Source
|
||||
* 0 floating-point unit
|
||||
* 1 local I/O 0
|
||||
* 2 local I/O 1
|
||||
* 3 timer 0
|
||||
* 4 timer 1
|
||||
* 5 bus error
|
||||
*/
|
||||
|
||||
#include "emu.h"
|
||||
#include "int2.h"
|
||||
|
||||
//#define VERBOSE (LOG_GENERAL)
|
||||
|
||||
#include "logmacro.h"
|
||||
|
||||
DEFINE_DEVICE_TYPE(SGI_INT2, sgi_int2_device, "sgi_int2", "SGI INT2")
|
||||
|
||||
sgi_int2_device::sgi_int2_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
|
||||
: device_t(mconfig, SGI_INT2, tag, owner, clock)
|
||||
, m_pit(*this, "pit")
|
||||
, m_vme(*this, "vme%u_int", 0U)
|
||||
, m_led(*this)
|
||||
, m_poweroff(*this)
|
||||
, m_intr(*this)
|
||||
, m_intr_state{}
|
||||
{
|
||||
}
|
||||
|
||||
void sgi_int2_device::device_add_mconfig(machine_config &config)
|
||||
{
|
||||
PIT8254(config, m_pit);
|
||||
m_pit->set_clk<2>(clock() / 10);
|
||||
m_pit->out_handler<0>().set([this](int state) { if (state) { m_intr_state[3] = true; m_intr[3](m_intr_state[3]); } });
|
||||
m_pit->out_handler<1>().set([this](int state) { if (state) { m_intr_state[4] = true; m_intr[4](m_intr_state[4]); } });
|
||||
m_pit->out_handler<2>().append(m_pit, FUNC(pit8254_device::write_clk0));
|
||||
m_pit->out_handler<2>().append(m_pit, FUNC(pit8254_device::write_clk1));
|
||||
|
||||
INPUT_MERGER_ANY_HIGH(config, m_vme[0]);
|
||||
m_vme[0]->output_handler().set(FUNC(sgi_int2_device::lio0_w<LIO0_VME0>));
|
||||
|
||||
INPUT_MERGER_ANY_HIGH(config, m_vme[1]);
|
||||
m_vme[1]->output_handler().set(FUNC(sgi_int2_device::lio1_w<LIO1_VME1>));
|
||||
}
|
||||
|
||||
void sgi_int2_device::device_start()
|
||||
{
|
||||
save_item(NAME(m_intr_state));
|
||||
save_item(NAME(m_lstatus));
|
||||
save_item(NAME(m_lmask));
|
||||
save_item(NAME(m_vstatus));
|
||||
save_item(NAME(m_vmask));
|
||||
save_item(NAME(m_config));
|
||||
|
||||
m_lstatus[0] = 0;
|
||||
m_lstatus[1] = 0;
|
||||
m_vstatus = 0;
|
||||
m_config = 0;
|
||||
}
|
||||
|
||||
void sgi_int2_device::device_reset()
|
||||
{
|
||||
config_w(0);
|
||||
|
||||
m_lmask[0] = 0;
|
||||
m_lmask[1] = 0;
|
||||
m_vmask[0] = 0;
|
||||
m_vmask[1] = 0;
|
||||
|
||||
lio_update();
|
||||
}
|
||||
|
||||
void sgi_int2_device::map(address_map &map)
|
||||
{
|
||||
map(0x0, 0x0).r(FUNC(sgi_int2_device::lstatus_r<0>));
|
||||
map(0x1, 0x1).rw(FUNC(sgi_int2_device::lmask_r<0>), FUNC(sgi_int2_device::lmask_w<0>));
|
||||
map(0x2, 0x2).r(FUNC(sgi_int2_device::lstatus_r<1>));
|
||||
map(0x3, 0x3).rw(FUNC(sgi_int2_device::lmask_r<1>), FUNC(sgi_int2_device::lmask_w<1>));
|
||||
map(0x4, 0x4).r(FUNC(sgi_int2_device::vstatus_r));
|
||||
map(0x5, 0x5).rw(FUNC(sgi_int2_device::vmask_r<0>), FUNC(sgi_int2_device::vmask_w<0>));
|
||||
map(0x6, 0x6).rw(FUNC(sgi_int2_device::vmask_r<1>), FUNC(sgi_int2_device::vmask_w<1>));
|
||||
map(0x7, 0x7).rw(FUNC(sgi_int2_device::config_r), FUNC(sgi_int2_device::config_w));
|
||||
map(0x8, 0x8).w(FUNC(sgi_int2_device::tclear_w));
|
||||
|
||||
map(0xc, 0xf).rw(m_pit, FUNC(pit8254_device::read), FUNC(pit8254_device::write));
|
||||
}
|
||||
|
||||
template <unsigned N> void sgi_int2_device::lmask_w(u8 data)
|
||||
{
|
||||
m_lmask[N] = data;
|
||||
|
||||
lio_update();
|
||||
}
|
||||
|
||||
template <unsigned N> void sgi_int2_device::vmask_w(u8 data)
|
||||
{
|
||||
m_vmask[N] = data;
|
||||
|
||||
lio_update();
|
||||
}
|
||||
|
||||
void sgi_int2_device::config_w(u8 data)
|
||||
{
|
||||
for (unsigned led = 0; led < 4; led++)
|
||||
if (BIT(data ^ m_config, led))
|
||||
m_led[led](BIT(data, led));
|
||||
|
||||
if (BIT(data ^ m_config, 4))
|
||||
m_poweroff(BIT(data, 4));
|
||||
|
||||
m_config = data & 0x1f;
|
||||
}
|
||||
|
||||
void sgi_int2_device::tclear_w(u8 data)
|
||||
{
|
||||
// clear timer 0 level 3
|
||||
if (BIT(data, 0) && m_intr_state[3])
|
||||
{
|
||||
m_intr_state[3] = false;
|
||||
m_intr[3](m_intr_state[3]);
|
||||
}
|
||||
|
||||
// clear timer 1 level 4
|
||||
if (BIT(data, 1) && m_intr_state[4])
|
||||
{
|
||||
m_intr_state[4] = false;
|
||||
m_intr[4](m_intr_state[4]);
|
||||
}
|
||||
}
|
||||
|
||||
template <unsigned N> void sgi_int2_device::lio0_w(int state)
|
||||
{
|
||||
LOG("lio0 interrupt %u input state %d\n", N, state);
|
||||
if (state)
|
||||
m_lstatus[0] |= 1U << N;
|
||||
else
|
||||
m_lstatus[0] &= ~(1U << N);
|
||||
|
||||
lio_update();
|
||||
}
|
||||
|
||||
template <unsigned N> void sgi_int2_device::lio1_w(int state)
|
||||
{
|
||||
LOG("lio1 interrupt %u input state %d\n", N, state);
|
||||
if (state)
|
||||
m_lstatus[1] |= 1U << N;
|
||||
else
|
||||
m_lstatus[1] &= ~(1U << N);
|
||||
|
||||
lio_update();
|
||||
}
|
||||
|
||||
template <unsigned N> void sgi_int2_device::vme_w(int state)
|
||||
{
|
||||
LOG("vme interrupt %u input state %d\n", N, state);
|
||||
if (state)
|
||||
m_vstatus |= 1U << N;
|
||||
else
|
||||
m_vstatus &= ~(1U << N);
|
||||
|
||||
m_vme[0]->in_w<N>(state);
|
||||
m_vme[1]->in_w<N>(state);
|
||||
}
|
||||
|
||||
void sgi_int2_device::lio_update()
|
||||
{
|
||||
for (unsigned l = 0; l < 2; l++)
|
||||
{
|
||||
if (bool(m_lstatus[l] & m_lmask[l]) != m_intr_state[l + 1])
|
||||
{
|
||||
LOG("lio%d output state %d\n", l, bool(m_lstatus[l] & m_lmask[l]));
|
||||
m_intr_state[l + 1] = m_lstatus[l] & m_lmask[l];
|
||||
m_intr[l + 1](m_intr_state[l + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template void sgi_int2_device::lio0_w<0>(int state);
|
||||
template void sgi_int2_device::lio0_w<1>(int state);
|
||||
template void sgi_int2_device::lio0_w<2>(int state);
|
||||
template void sgi_int2_device::lio0_w<3>(int state);
|
||||
template void sgi_int2_device::lio0_w<4>(int state);
|
||||
template void sgi_int2_device::lio0_w<5>(int state);
|
||||
template void sgi_int2_device::lio0_w<6>(int state);
|
||||
template void sgi_int2_device::lio0_w<7>(int state);
|
||||
|
||||
template void sgi_int2_device::lio1_w<0>(int state);
|
||||
template void sgi_int2_device::lio1_w<1>(int state);
|
||||
template void sgi_int2_device::lio1_w<2>(int state);
|
||||
template void sgi_int2_device::lio1_w<3>(int state);
|
||||
template void sgi_int2_device::lio1_w<4>(int state);
|
||||
template void sgi_int2_device::lio1_w<5>(int state);
|
||||
template void sgi_int2_device::lio1_w<6>(int state);
|
||||
template void sgi_int2_device::lio1_w<7>(int state);
|
||||
|
||||
template void sgi_int2_device::vme_w<1>(int state);
|
||||
template void sgi_int2_device::vme_w<2>(int state);
|
||||
template void sgi_int2_device::vme_w<3>(int state);
|
||||
template void sgi_int2_device::vme_w<4>(int state);
|
||||
template void sgi_int2_device::vme_w<5>(int state);
|
||||
template void sgi_int2_device::vme_w<6>(int state);
|
||||
template void sgi_int2_device::vme_w<7>(int state);
|
86
src/mame/sgi/int2.h
Normal file
86
src/mame/sgi/int2.h
Normal file
@ -0,0 +1,86 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Patrick Mackinlay
|
||||
|
||||
#ifndef MAME_SGI_INT2_H
|
||||
#define MAME_SGI_INT2_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "machine/input_merger.h"
|
||||
#include "machine/pit8253.h"
|
||||
|
||||
class sgi_int2_device
|
||||
: public device_t
|
||||
{
|
||||
public:
|
||||
sgi_int2_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
template <unsigned N> auto write_led() { return m_led[N].bind(); }
|
||||
auto write_poweroff() { return m_poweroff.bind(); }
|
||||
template <unsigned N> auto write_intr() { return m_intr[N].bind(); }
|
||||
|
||||
enum lio_int : unsigned
|
||||
{
|
||||
LIO0_GIO0 = 0, // gio0/fifo full
|
||||
LIO0_PARALLEL = 1,
|
||||
LIO0_SCSI = 2,
|
||||
LIO0_ETHERNET = 3,
|
||||
LIO0_GDMA = 4, // graphics dma done
|
||||
LIO0_DUART = 5,
|
||||
LIO0_GIO1 = 6, // gio1/ge/second hpc1
|
||||
LIO0_VME0 = 7,
|
||||
|
||||
LIO1_GR1MODE = 1,
|
||||
LIO1_VME1 = 3,
|
||||
LIO1_DSP = 4, // hpc
|
||||
LIO1_ACFAIL = 5,
|
||||
LIO1_VIDEO = 6, // video option
|
||||
LIO1_GIO2 = 7, // gio2/vertical retrace
|
||||
};
|
||||
// interrupt request inputs
|
||||
template <unsigned N> void lio0_w(int state);
|
||||
template <unsigned N> void lio1_w(int state);
|
||||
template <unsigned N> void vme_w(int state);
|
||||
|
||||
void map(address_map &map);
|
||||
|
||||
protected:
|
||||
// device_t implementation
|
||||
void device_add_mconfig(machine_config &config) override;
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
// read handlers
|
||||
template <unsigned N> u8 lstatus_r() { return m_lstatus[N]; }
|
||||
template <unsigned N> u8 lmask_r() { return m_lmask[N]; }
|
||||
u8 vstatus_r() { return m_vstatus; }
|
||||
template <unsigned N> u8 vmask_r() { return m_vmask[N]; }
|
||||
u8 config_r() { return m_config; }
|
||||
|
||||
// write handlers
|
||||
template <unsigned N> void lmask_w(u8 data);
|
||||
template <unsigned N> void vmask_w(u8 data);
|
||||
void config_w(u8 data);
|
||||
void tclear_w(u8 data);
|
||||
|
||||
void lio_update();
|
||||
|
||||
private:
|
||||
required_device<pit8254_device> m_pit;
|
||||
required_device_array<input_merger_any_high_device, 2> m_vme;
|
||||
|
||||
devcb_write_line::array<4> m_led;
|
||||
devcb_write_line m_poweroff;
|
||||
devcb_write_line::array<6> m_intr;
|
||||
bool m_intr_state[6];
|
||||
|
||||
u8 m_lstatus[2];
|
||||
u8 m_lmask[2];
|
||||
u8 m_vstatus;
|
||||
u8 m_vmask[2];
|
||||
u8 m_config;
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(SGI_INT2, sgi_int2_device)
|
||||
|
||||
#endif // MAME_SGI_INT2_H
|
431
src/mame/sgi/ip12.cpp
Normal file
431
src/mame/sgi/ip12.cpp
Normal file
@ -0,0 +1,431 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Patrick Mackinlay
|
||||
|
||||
/*
|
||||
* Silicon Graphics IP12 systems.
|
||||
*
|
||||
* Year Model Board Type CPU Clock I/D Cache Code Name(s)
|
||||
* 1991 4D/30 IP14 IP12 R3000 30MHz 64KiB/64KiB Magnum
|
||||
* 1991 4D/35 IP12 IP12 R3000 36MHz 64KiB/64KiB Magnum
|
||||
* 1991 Indigo IP12 IP12 R3000 33MHz 32KiB/32KiB Hollywood, 4DRPC, HP1
|
||||
*
|
||||
* TODO:
|
||||
* - VME-based V30/V35
|
||||
* - DSP
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* WIP
|
||||
* ---
|
||||
* setenv bootmode d # enable diagnostic output (bootmode c is normal)
|
||||
*
|
||||
* ide usage: report=5; <test>
|
||||
*
|
||||
* installing IRIX 4.0.5/5.3 (IRIX CDROM at SCSI ID 4):
|
||||
* - boot -f dksc(0,4,8)sashIP12
|
||||
* - boot -f dksc(0,4,7)stand/fx.IP12 --x
|
||||
* - create root partition and label disk
|
||||
* - use firmware option 2 and inst to install OS from CDROM
|
||||
*
|
||||
* after installation, disable windowing system (until graphics work):
|
||||
* - shroot (or sh and prefix commands with chroot /root)
|
||||
* - /etc/chkconfig -f windowsystem off
|
||||
* - /etc/chkconfig -f xdm off
|
||||
* - for IRIX 5.3, also edit /etc/inittab to spawn getty on console
|
||||
*
|
||||
*/
|
||||
|
||||
#include "emu.h"
|
||||
#include "cpu/mips/mips1.h"
|
||||
#include "cpu/dsp56000/dsp56000.h"
|
||||
|
||||
#include "machine/dp8573a.h"
|
||||
#include "machine/edlc.h"
|
||||
#include "machine/eepromser.h"
|
||||
#include "machine/input_merger.h"
|
||||
#include "machine/nscsi_bus.h"
|
||||
#include "machine/wd33c9x.h"
|
||||
#include "machine/z80scc.h"
|
||||
|
||||
#include "bus/rs232/rs232.h"
|
||||
#include "bus/rs232/hlemouse.h"
|
||||
#include "bus/nscsi/cd.h"
|
||||
#include "bus/nscsi/hd.h"
|
||||
|
||||
#include "hpc1.h"
|
||||
#include "int2.h"
|
||||
#include "kbd.h"
|
||||
#include "light.h"
|
||||
#include "pic1.h"
|
||||
|
||||
//#define VERBOSE (LOG_GENERAL)
|
||||
#include "logmacro.h"
|
||||
|
||||
namespace {
|
||||
|
||||
class ip12_state : public driver_device
|
||||
{
|
||||
public:
|
||||
ip12_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: driver_device(mconfig, type, tag)
|
||||
, m_cpu(*this, "cpu")
|
||||
, m_pic(*this, "pic")
|
||||
, m_hpc(*this, "hpc")
|
||||
, m_int(*this, "int")
|
||||
, m_nvram(*this, "nvram")
|
||||
, m_rtc(*this, "rtc")
|
||||
, m_scsi(*this, "scsi:0:wd33c93a")
|
||||
, m_eth(*this, "eth")
|
||||
, m_scc(*this, "scc%u", 0U)
|
||||
, m_scc_irq(*this, "scc_irq")
|
||||
, m_dsp(*this, "dsp")
|
||||
, m_gfx(*this, "gfx")
|
||||
{
|
||||
}
|
||||
|
||||
void indigo(machine_config &config);
|
||||
void pi4d30(machine_config &config);
|
||||
void pi4d35(machine_config &config);
|
||||
|
||||
protected:
|
||||
virtual void machine_start() override;
|
||||
virtual void machine_reset() override;
|
||||
|
||||
void ip12(machine_config &config);
|
||||
void pi4d3x(machine_config &config);
|
||||
|
||||
void ip12_map(address_map &map);
|
||||
void pi4d3x_map(address_map &map);
|
||||
void pbus_map(address_map &map);
|
||||
|
||||
required_device<r3000a_device> m_cpu;
|
||||
required_device<sgi_pic1_device> m_pic;
|
||||
required_device<hpc1_device> m_hpc;
|
||||
required_device<sgi_int2_device> m_int;
|
||||
required_device<eeprom_serial_93cxx_device> m_nvram;
|
||||
required_device<dp8572a_device> m_rtc;
|
||||
required_device<wd33c93a_device> m_scsi;
|
||||
required_device<seeq8003_device> m_eth;
|
||||
required_device_array<scc85c30_device, 3> m_scc;
|
||||
required_device<input_merger_any_high_device> m_scc_irq;
|
||||
required_device<dsp56001_device> m_dsp;
|
||||
required_device<sgi_lg1_device> m_gfx;
|
||||
|
||||
/*
|
||||
* board revisions according to NetBSD source:
|
||||
* 0x0000-0x6000 -> IP12 4D/3x
|
||||
* 0x7000 -> IP12 VIP12
|
||||
* 0x8000-0xd000 -> IP12 HP1
|
||||
* 0xe000-0xf000 -> IP12 HPLC
|
||||
*/
|
||||
u32 m_brdrev;
|
||||
};
|
||||
|
||||
void ip12_state::machine_start()
|
||||
{
|
||||
}
|
||||
|
||||
void ip12_state::machine_reset()
|
||||
{
|
||||
}
|
||||
|
||||
void ip12_state::ip12_map(address_map &map)
|
||||
{
|
||||
// 0x0000'0000-0fff'ffff // local memory
|
||||
// 0x1000'0000-1eff'ffff // vme
|
||||
// 0x1f00'0000-1fbf'ffff // local i/o
|
||||
// 0x1fc0'0000-1fff'ffff // boot prom
|
||||
|
||||
// 0x2000'0000-3fff'ffff // vme (normally inaccessible)
|
||||
// 0x4000'0000-ffff'ffff // unused (normally inaccessible), bus error (read) interrupt (write)
|
||||
|
||||
map(0x1000'0000, 0x1eff'ffff).lr32([this]() { m_cpu->berr_w(1); return 0; }, "buserror"); // vme
|
||||
|
||||
map(0x1f3f'0000, 0x1f3f'7fff).m(m_gfx, FUNC(sgi_lg1_device::map));
|
||||
// 1f3f'8000-1f3f'ffff // lg2x2 second head
|
||||
|
||||
// 0x1f40'0000-0x1f5'ffff gio slot 0
|
||||
// 0x1f60'0000-0x1f7'ffff gio slot 1
|
||||
|
||||
//map(0x1f90'0000, 0x1f97'ffff); // hpc 3
|
||||
//map(0x1f98'0000, 0x1f9f'ffff); // hpc 2
|
||||
map(0x1fa0'0000, 0x1faf'ffff).m(m_pic, FUNC(sgi_pic1_device::map));
|
||||
//map(0x1fb0'0000, 0x1fb7'ffff); // hpc 1
|
||||
//map(0x1fb8'0000, 0x1fbf'ffff); // hpc 0
|
||||
|
||||
map(0x1fb8'0000, 0x1fb8'ffff).m(m_hpc, FUNC(hpc1_device::map));
|
||||
map(0x1fb8'0100, 0x1fb8'011f).m(m_eth, FUNC(seeq8003_device::map)).umask32(0xff);
|
||||
map(0x1fb8'0120, 0x1fb8'0127).rw(m_scsi, FUNC(wd33c93a_device::indir_r), FUNC(wd33c93a_device::indir_w)).umask32(0xff00);
|
||||
map(0x1fb8'01c0, 0x1fb8'01ff).m(m_int, FUNC(sgi_int2_device::map)).umask32(0xff);
|
||||
map(0x1fb8'0d00, 0x1fb8'0d0f).rw(m_scc[0], FUNC(scc85c30_device::ab_dc_r), FUNC(scc85c30_device::ab_dc_w)).umask32(0xff);
|
||||
map(0x1fb8'0d10, 0x1fb8'0d1f).rw(m_scc[1], FUNC(scc85c30_device::ab_dc_r), FUNC(scc85c30_device::ab_dc_w)).umask32(0xff);
|
||||
map(0x1fb8'0d30, 0x1fb8'0d3f).noprw(); // TODO: left/right headphone gain mdacs
|
||||
map(0x1fb8'0e00, 0x1fb8'0e7f).rw(m_rtc, FUNC(dp8572a_device::read), FUNC(dp8572a_device::write)).umask32(0xff);
|
||||
|
||||
map(0x1fbd'0000, 0x1fbd'0003).lr32([this]() { return m_brdrev; }, "board_rev"); // board revision register
|
||||
|
||||
map(0x1fbe'0000, 0x1fbf'ffff).ram().share("dsp_ram"); // 3xTC55328J-35 (24 bits x 32k)
|
||||
|
||||
map(0x1fc0'0000, 0x1fc3'ffff).rom().region("prom", 0);
|
||||
}
|
||||
|
||||
void ip12_state::pi4d3x_map(address_map &map)
|
||||
{
|
||||
ip12_map(map);
|
||||
|
||||
map(0x1fb8'0d20, 0x1fb8'0d2f).rw(m_scc[2], FUNC(scc85c30_device::ab_dc_r), FUNC(scc85c30_device::ab_dc_w)).umask32(0xff);
|
||||
}
|
||||
|
||||
// HPC1 PBUS decode?
|
||||
// 00100-0011f == 00040-00047 -> net
|
||||
// 00120-00127 == 00048-00049 -> scsi
|
||||
// 001c0-001ff == 00070-0007f -> int2
|
||||
// 00d00-00d3f == 00340-0034f -> fff0-ffff duart
|
||||
// 00e00-00e7f == 00380-0039f -> ffc0-ffdf rtc
|
||||
// 60000-7ffff == 18000-1ffff -> 8000-ffff? ram
|
||||
//
|
||||
// Actel/AUD1 and audio adc/dac via DSP SCI
|
||||
//
|
||||
void ip12_state::pbus_map(address_map &map)
|
||||
{
|
||||
map(0xffc0, 0xffdf).rw(m_rtc, FUNC(dp8572a_device::read), FUNC(dp8572a_device::write));
|
||||
|
||||
map(0xfff0, 0xfff3).rw(m_scc[0], FUNC(scc85c30_device::ab_dc_r), FUNC(scc85c30_device::ab_dc_w));
|
||||
map(0xfff4, 0xfff7).rw(m_scc[1], FUNC(scc85c30_device::ab_dc_r), FUNC(scc85c30_device::ab_dc_w));
|
||||
map(0xfff8, 0xfffb).rw(m_scc[2], FUNC(scc85c30_device::ab_dc_r), FUNC(scc85c30_device::ab_dc_w));
|
||||
//map(0xfffc, 0xffff).rw(m_scc[3], FUNC(scc85c30_device::ab_dc_r), FUNC(scc85c30_device::ab_dc_w));
|
||||
}
|
||||
|
||||
static DEVICE_INPUT_DEFAULTS_START(pi4d3x_pic1)
|
||||
DEVICE_INPUT_DEFAULTS("VALID", 0x0f, 0x0f)
|
||||
DEVICE_INPUT_DEFAULTS_END
|
||||
|
||||
static DEVICE_INPUT_DEFAULTS_START(indigo_pic1)
|
||||
DEVICE_INPUT_DEFAULTS("VALID", 0x0f, 0x07)
|
||||
DEVICE_INPUT_DEFAULTS_END
|
||||
|
||||
static void scsi_devices(device_slot_interface &device)
|
||||
{
|
||||
device.option_add("cdrom", NSCSI_CDROM_SGI).machine_config(
|
||||
[](device_t *device)
|
||||
{
|
||||
downcast<nscsi_cdrom_device &>(*device).set_block_size(512);
|
||||
});
|
||||
device.option_add("harddisk", NSCSI_HARDDISK);
|
||||
}
|
||||
|
||||
void ip12_state::ip12(machine_config &config)
|
||||
{
|
||||
SGI_PIC1(config, m_pic, 0);
|
||||
m_pic->set_bus(m_cpu, AS_PROGRAM);
|
||||
|
||||
SGI_HPC1(config, m_hpc, 0);
|
||||
m_hpc->set_addrmap(0, &ip12_state::pbus_map);
|
||||
m_hpc->set_gio(m_cpu, AS_PROGRAM);
|
||||
m_hpc->set_enet(m_eth);
|
||||
m_hpc->int_w().set(m_int, FUNC(sgi_int2_device::lio0_w<sgi_int2_device::LIO0_ETHERNET>));
|
||||
m_hpc->dma_r_cb<0>().set(m_scsi, FUNC(wd33c93a_device::dma_r));
|
||||
m_hpc->dma_w_cb<0>().set(m_scsi, FUNC(wd33c93a_device::dma_w));
|
||||
m_hpc->eeprom_dati().set(m_nvram, FUNC(eeprom_serial_93cxx_device::do_read));
|
||||
m_hpc->eeprom_out().set(
|
||||
[this](u8 data)
|
||||
{
|
||||
// TODO: bit 0 console led
|
||||
m_nvram->di_write(BIT(data, 3));
|
||||
m_nvram->cs_write(BIT(data, 1));
|
||||
m_nvram->clk_write(BIT(data, 2));
|
||||
});
|
||||
|
||||
SGI_INT2(config, m_int, 10_MHz_XTAL);
|
||||
m_int->write_intr<1>().set_inputline(m_cpu, INPUT_LINE_IRQ1);
|
||||
m_int->write_intr<2>().set_inputline(m_cpu, INPUT_LINE_IRQ2);
|
||||
m_int->write_intr<3>().set_inputline(m_cpu, INPUT_LINE_IRQ3);
|
||||
m_int->write_intr<4>().set_inputline(m_cpu, INPUT_LINE_IRQ4);
|
||||
m_int->write_intr<5>().set_inputline(m_cpu, INPUT_LINE_IRQ5);
|
||||
// TODO: write_led and write_poweroff outputs
|
||||
//
|
||||
// 0 scc.clk.sel external clock on for hp1 port 0
|
||||
// 1 ser0.sel rts/tx+ for hp1 port 0 (rts=1)
|
||||
// 2 ser1.sel rts/tx+ for hp1 port 1 (rts=1)
|
||||
// 3 clr.retrace- disable/enable vert. retrace intr.
|
||||
// 4 poweroff
|
||||
|
||||
EEPROM_93C56_16BIT(config, m_nvram);
|
||||
|
||||
DP8572A(config, m_rtc, 32.768_kHz_XTAL).set_use_utc(true);
|
||||
|
||||
NSCSI_BUS(config, "scsi", 0);
|
||||
NSCSI_CONNECTOR(config, "scsi:0").option_set("wd33c93a", WD33C93A).machine_config(
|
||||
[this](device_t *device)
|
||||
{
|
||||
wd33c93a_device &scsi = downcast<wd33c93a_device &>(*device);
|
||||
|
||||
scsi.set_clock(10_MHz_XTAL);
|
||||
scsi.irq_cb().set(m_int, FUNC(sgi_int2_device::lio0_w<sgi_int2_device::LIO0_SCSI>));
|
||||
scsi.drq_cb().set(m_hpc, FUNC(hpc1_device::write_drq<0>));
|
||||
});
|
||||
NSCSI_CONNECTOR(config, "scsi:1", scsi_devices, "harddisk", false);
|
||||
NSCSI_CONNECTOR(config, "scsi:2", scsi_devices, nullptr, false);
|
||||
NSCSI_CONNECTOR(config, "scsi:3", scsi_devices, nullptr, false);
|
||||
NSCSI_CONNECTOR(config, "scsi:4", scsi_devices, "cdrom", false);
|
||||
NSCSI_CONNECTOR(config, "scsi:5", scsi_devices, nullptr, false);
|
||||
NSCSI_CONNECTOR(config, "scsi:6", scsi_devices, nullptr, false);
|
||||
NSCSI_CONNECTOR(config, "scsi:7", scsi_devices, nullptr, false);
|
||||
|
||||
SEEQ8003(config, m_eth, 0);
|
||||
m_eth->out_int_cb().set(m_hpc, FUNC(hpc1_device::write_int));
|
||||
m_eth->out_rxrdy_cb().set(m_hpc, FUNC(hpc1_device::write_drq<1>));
|
||||
m_hpc->dma_r_cb<1>().set(m_eth, FUNC(seeq8003_device::fifo_r));
|
||||
m_hpc->dma_w_cb<1>().set(m_eth, FUNC(seeq8003_device::fifo_w));
|
||||
|
||||
// 24.576MHz
|
||||
// 22.5792MHz
|
||||
// 3.6720MHz
|
||||
input_merger_any_high_device &scc_irq(INPUT_MERGER_ANY_HIGH(config, "scc_irq"));
|
||||
scc_irq.output_handler().set(m_int, FUNC(sgi_int2_device::lio0_w<sgi_int2_device::LIO0_DUART>));
|
||||
|
||||
// duart 0: keyboard/mouse ports
|
||||
SCC85C30(config, m_scc[0], 10_MHz_XTAL);
|
||||
m_scc[0]->configure_channels(3'686'400, 0, 3'686'400, 0);
|
||||
m_scc[0]->out_int_callback().set(scc_irq, FUNC(input_merger_any_high_device::in_w<0>));
|
||||
|
||||
sgi_kbd_port_device &kbd_port(SGI_KBD_PORT(config, "keyboard_port"));
|
||||
kbd_port.option_set("keyboard", SGI_KBD);
|
||||
rs232_port_device &mouse_port(RS232_PORT(config, "mouse_port", 0));
|
||||
mouse_port.option_set("mouse", SGI_HLE_SERIAL_MOUSE);
|
||||
m_scc[0]->out_txda_callback().set(kbd_port, FUNC(sgi_kbd_port_device::write_txd));
|
||||
kbd_port.rxd_handler().set(m_scc[0], FUNC(scc85c30_device::rxa_w));
|
||||
mouse_port.rxd_handler().set(m_scc[0], FUNC(scc85c30_device::rxb_w));
|
||||
|
||||
// duart 1: serial ports
|
||||
SCC85C30(config, m_scc[1], 10_MHz_XTAL);
|
||||
m_scc[1]->configure_channels(3'686'400, 0, 3'686'400, 0);
|
||||
m_scc[1]->out_int_callback().set(scc_irq, FUNC(input_merger_any_high_device::in_w<1>));
|
||||
|
||||
rs232_port_device &rs232a(RS232_PORT(config, "rs232a", default_rs232_devices, nullptr));
|
||||
rs232_port_device &rs232b(RS232_PORT(config, "rs232b", default_rs232_devices, nullptr));
|
||||
m_scc[1]->out_txda_callback().set(rs232a, FUNC(rs232_port_device::write_txd));
|
||||
m_scc[1]->out_dtra_callback().set(rs232a, FUNC(rs232_port_device::write_dtr));
|
||||
m_scc[1]->out_rtsa_callback().set(rs232a, FUNC(rs232_port_device::write_rts));
|
||||
m_scc[1]->out_txdb_callback().set(rs232b, FUNC(rs232_port_device::write_txd));
|
||||
m_scc[1]->out_dtrb_callback().set(rs232b, FUNC(rs232_port_device::write_dtr));
|
||||
m_scc[1]->out_rtsb_callback().set(rs232b, FUNC(rs232_port_device::write_rts));
|
||||
rs232a.cts_handler().set(m_scc[1], FUNC(scc85c30_device::ctsa_w));
|
||||
rs232a.dcd_handler().set(m_scc[1], FUNC(scc85c30_device::dcda_w));
|
||||
rs232a.rxd_handler().set(m_scc[1], FUNC(scc85c30_device::rxa_w));
|
||||
rs232b.cts_handler().set(m_scc[1], FUNC(scc85c30_device::ctsb_w));
|
||||
rs232b.dcd_handler().set(m_scc[1], FUNC(scc85c30_device::dcdb_w));
|
||||
rs232b.rxd_handler().set(m_scc[1], FUNC(scc85c30_device::rxb_w));
|
||||
|
||||
// duart 2: "Apple" RS-422 serial ports (4D/PI only)
|
||||
SCC85C30(config, m_scc[2], 10_MHz_XTAL); // Z8513010VSC ESCC
|
||||
m_scc[2]->configure_channels(3'686'400, 0, 3'686'400, 0);
|
||||
m_scc[2]->out_int_callback().set(scc_irq, FUNC(input_merger_any_high_device::in_w<1>));
|
||||
|
||||
DSP56001(config, m_dsp, 20_MHz_XTAL);
|
||||
//m_dsp->moda_w(1);
|
||||
//m_dsp->modb_w(0);
|
||||
|
||||
SGI_LG1(config, m_gfx);
|
||||
m_gfx->write_vblank().set(m_int, FUNC(sgi_int2_device::lio1_w<sgi_int2_device::LIO1_GIO2>));
|
||||
}
|
||||
|
||||
void ip12_state::pi4d3x(machine_config &config)
|
||||
{
|
||||
ip12(config);
|
||||
|
||||
m_pic->set_input_default(DEVICE_INPUT_DEFAULTS_NAME(pi4d3x_pic1));
|
||||
|
||||
// serial port 3
|
||||
// FIXME: HSKO/HSKI/GPI
|
||||
rs232_port_device &rs232c(RS232_PORT(config, "rs232c", default_rs232_devices, nullptr));
|
||||
m_scc[2]->out_txda_callback().set(rs232c, FUNC(rs232_port_device::write_txd));
|
||||
rs232c.rxd_handler().set(m_scc[2], FUNC(z80scc_device::rxa_w));
|
||||
|
||||
// serial port 4
|
||||
// FIXME: HSKO/HSKI/GPI
|
||||
rs232_port_device &rs232d(RS232_PORT(config, "rs232d", default_rs232_devices, nullptr));
|
||||
m_scc[2]->out_txdb_callback().set(rs232d, FUNC(rs232_port_device::write_txd));
|
||||
rs232d.rxd_handler().set(m_scc[2], FUNC(z80scc_device::rxb_w));
|
||||
}
|
||||
|
||||
void ip12_state::indigo(machine_config &config)
|
||||
{
|
||||
R3000A(config, m_cpu, 66.0_MHz_XTAL / 2, 32768, 32768);
|
||||
m_cpu->set_addrmap(AS_PROGRAM, &ip12_state::ip12_map);
|
||||
// FIXME: route fpu interrupt via int2
|
||||
m_cpu->set_fpu(r3000a_device::MIPS_R3010A, INPUT_LINE_IRQ0);
|
||||
|
||||
ip12(config);
|
||||
|
||||
m_pic->set_input_default(DEVICE_INPUT_DEFAULTS_NAME(indigo_pic1));
|
||||
|
||||
m_brdrev = 0x8000;
|
||||
}
|
||||
|
||||
void ip12_state::pi4d30(machine_config &config)
|
||||
{
|
||||
R3000A(config, m_cpu, 30_MHz_XTAL, 65536, 65536);
|
||||
m_cpu->set_addrmap(AS_PROGRAM, &ip12_state::pi4d3x_map);
|
||||
// FIXME: route fpu interrupt via int2
|
||||
m_cpu->set_fpu(r3000a_device::MIPS_R3010A, INPUT_LINE_IRQ0);
|
||||
|
||||
pi4d3x(config);
|
||||
|
||||
m_brdrev = 0x0000;
|
||||
}
|
||||
|
||||
void ip12_state::pi4d35(machine_config &config)
|
||||
{
|
||||
R3000A(config, m_cpu, 36_MHz_XTAL, 65536, 65536);
|
||||
m_cpu->set_addrmap(AS_PROGRAM, &ip12_state::pi4d3x_map);
|
||||
// FIXME: route fpu interrupt via int2
|
||||
m_cpu->set_fpu(r3000a_device::MIPS_R3010A, INPUT_LINE_IRQ0);
|
||||
|
||||
pi4d3x(config);
|
||||
|
||||
// FIXME: higher revisions fail scsi power fuse diagnostic
|
||||
m_brdrev = 0x0000;
|
||||
}
|
||||
|
||||
ROM_START(indigo)
|
||||
ROM_REGION32_BE(0x40000, "prom", 0) // Am27C2048 128Kx16
|
||||
|
||||
// dumped over serial connection from boot monitor and swapped
|
||||
ROM_SYSTEM_BIOS(0, "401-rev-c", "SGI Version 4.0.1 Rev C LG1/GR2, Jul 9, 1992")
|
||||
ROMX_LOAD("ip12prom.070-8088-xxx.u56", 0x000000, 0x040000, CRC(25ca912f) SHA1(94b3753d659bfe50b914445cef41290122f43880), ROM_GROUPWORD | ROM_REVERSE | ROM_BIOS(0))
|
||||
|
||||
// dumped with EPROM programmer
|
||||
ROM_SYSTEM_BIOS(1, "401-rev-d", "SGI Version 4.0.1 Rev D LG1/GR2, Mar 24, 1992")
|
||||
ROMX_LOAD("ip12prom.070-8088-002.u56", 0x000000, 0x040000, CRC(ea4329ef) SHA1(b7d67d0e30ae8836892f7170dd4757732a0a3fd6), ROM_GROUPWORD | ROM_REVERSE | ROM_BIOS(1))
|
||||
|
||||
ROM_SYSTEM_BIOS(2, "sni", "SGI Version 4.0.1 Rev C LG1/GR2, Feb 14, 1992")
|
||||
ROMX_LOAD("070-8088-001__a.u56", 0x000000, 0x040000, CRC(40eae7a0) SHA1(d60ef74cf04a16d9dad6b9594a66724d944b1208), ROM_GROUPWORD | ROM_REVERSE | ROM_BIOS(2))
|
||||
ROM_END
|
||||
|
||||
ROM_START(pi4d30)
|
||||
ROM_REGION32_BE(0x80000, "prom", 0)
|
||||
ROM_SYSTEM_BIOS(0, "4.0.1c", "SGI Version 4.0.1 Rev C GR1/GR2/LG1, Feb 14, 1992")
|
||||
ROMX_LOAD("ip14prom.bin", 0x000000, 0x080000, NO_DUMP, ROM_BIOS(0))
|
||||
ROM_END
|
||||
|
||||
ROM_START(pi4d35)
|
||||
ROM_REGION32_BE(0x80000, "prom", 0) // TC574096D-120 (262,144x16-bit EEPROM)
|
||||
|
||||
ROM_SYSTEM_BIOS(0, "4.0.1d", "SGI Version 4.0.1 Rev D LG1/GR2, Mar 24, 1992")
|
||||
ROMX_LOAD("ip12prom.002be.u61", 0x000000, 0x040000, CRC(d35f105c) SHA1(3d08dfb961d7512bd8ed41cb6e01e89d14134f09), ROM_BIOS(0))
|
||||
|
||||
ROM_SYSTEM_BIOS(1, "4.0.1c", "SGI Version 4.0.1 Rev C GR1/GR2/LG1, Feb 14, 1992")
|
||||
ROMX_LOAD("ip12prom.070-8086-002.u61", 0x000000, 0x080000, CRC(543cfc3f) SHA1(a7331876f11bff40c960f822923503eca17191c5), ROM_BIOS(1))
|
||||
|
||||
ROM_SYSTEM_BIOS(2, "4.0a", "SGI Version 4.0 Rev A IP12, Aug 22, 1991")
|
||||
ROMX_LOAD("ip12prom.070-8045-002.u61", 0x000000, 0x040000, CRC(fe999bae) SHA1(eb054c365a6e018be3b9ae44169c0ffc6447c6f0), ROM_BIOS(2))
|
||||
ROM_END
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
|
||||
COMP(1991, pi4d30, 0, 0, pi4d30, 0, ip12_state, empty_init, "Silicon Graphics", "Personal IRIS 4D/30", MACHINE_NO_SOUND | MACHINE_IMPERFECT_GRAPHICS)
|
||||
COMP(1991, pi4d35, 0, 0, pi4d35, 0, ip12_state, empty_init, "Silicon Graphics", "Personal IRIS 4D/35", MACHINE_NO_SOUND | MACHINE_IMPERFECT_GRAPHICS)
|
||||
COMP(1991, indigo, 0, 0, indigo, 0, ip12_state, empty_init, "Silicon Graphics", "IRIS Indigo", MACHINE_NO_SOUND | MACHINE_IMPERFECT_GRAPHICS)
|
291
src/mame/sgi/ip20.cpp
Normal file
291
src/mame/sgi/ip20.cpp
Normal file
@ -0,0 +1,291 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Patrick Mackinlay
|
||||
|
||||
/*
|
||||
* Silicon Graphics Indigo R4000/R4400 aka 4DRPC-50/Blackjack/HP2 (also VME-based V50)
|
||||
*
|
||||
* INT2 local I/O interrupt multiplexor
|
||||
* HPC1.5 high-performance peripheral controller
|
||||
* MC memory controller
|
||||
*
|
||||
*/
|
||||
/* board revs of IP20 are: 1 & 2 were early blackjack spins
|
||||
* 10 decimal == 0x0a == 1010binary == VME IP 20 board (V50)
|
||||
* V50 board lacks audio hardware
|
||||
* The upper bit used to change the standard (rev 2) board
|
||||
* to the V50 designation (i.e the 0x8 bit) used to be known
|
||||
* internally as the 'Hollywood processor 1 bit' or hp1 bit
|
||||
*/
|
||||
|
||||
#include "emu.h"
|
||||
#include "cpu/mips/r4000.h"
|
||||
#include "cpu/dsp56000/dsp56000.h"
|
||||
|
||||
#include "machine/dp8573a.h"
|
||||
#include "machine/edlc.h"
|
||||
#include "machine/eepromser.h"
|
||||
#include "machine/input_merger.h"
|
||||
#include "machine/nscsi_bus.h"
|
||||
#include "machine/wd33c9x.h"
|
||||
#include "machine/z80scc.h"
|
||||
|
||||
#include "bus/rs232/rs232.h"
|
||||
#include "bus/rs232/hlemouse.h"
|
||||
#include "bus/nscsi/cd.h"
|
||||
#include "bus/nscsi/hd.h"
|
||||
|
||||
#include "hpc1.h"
|
||||
#include "int2.h"
|
||||
#include "kbd.h"
|
||||
#include "light.h"
|
||||
#include "mc.h"
|
||||
|
||||
//#define VERBOSE (LOG_GENERAL)
|
||||
#include "logmacro.h"
|
||||
|
||||
namespace {
|
||||
|
||||
class ip20_state : public driver_device
|
||||
{
|
||||
public:
|
||||
ip20_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: driver_device(mconfig, type, tag)
|
||||
, m_cpu(*this, "cpu")
|
||||
, m_eerom(*this, "eerom")
|
||||
, m_mc(*this, "mc")
|
||||
, m_hpc(*this, "hpc")
|
||||
, m_int(*this, "int")
|
||||
, m_nvram(*this, "nvram")
|
||||
, m_rtc(*this, "rtc")
|
||||
, m_scsi(*this, "scsi:0:wd33c93a")
|
||||
, m_eth(*this, "eth")
|
||||
, m_scc(*this, "scc%u", 0U)
|
||||
, m_dsp(*this, "dsp")
|
||||
, m_gfx(*this, "gfx")
|
||||
{
|
||||
}
|
||||
|
||||
void indigo_r4000(machine_config &config);
|
||||
void indigo_r4400(machine_config &config);
|
||||
|
||||
protected:
|
||||
void ip20(machine_config &config);
|
||||
|
||||
virtual void machine_start() override;
|
||||
virtual void machine_reset() override;
|
||||
|
||||
void cpu_map(address_map &map);
|
||||
|
||||
required_device<r4000_base_device> m_cpu;
|
||||
required_device<eeprom_serial_93cxx_device> m_eerom;
|
||||
required_device<sgi_mc_device> m_mc;
|
||||
required_device<hpc1_device> m_hpc;
|
||||
required_device<sgi_int2_device> m_int;
|
||||
required_device<eeprom_serial_93cxx_device> m_nvram;
|
||||
required_device<dp8572a_device> m_rtc;
|
||||
required_device<wd33c93a_device> m_scsi;
|
||||
required_device<seeq8003_device> m_eth;
|
||||
required_device_array<scc85c30_device, 3> m_scc;
|
||||
required_device<dsp56001_device> m_dsp;
|
||||
required_device<sgi_lg1_device> m_gfx;
|
||||
};
|
||||
|
||||
void ip20_state::machine_start()
|
||||
{
|
||||
}
|
||||
|
||||
void ip20_state::machine_reset()
|
||||
{
|
||||
}
|
||||
|
||||
void ip20_state::cpu_map(address_map &map)
|
||||
{
|
||||
//map(0x1fbd9000, 0x1fbd903f).rw(FUNC(indigo_state::int_r), FUNC(indigo_state::int_w));
|
||||
|
||||
//map(0x0000'0000, 0x0007'ffff); // system memory alias (512K)
|
||||
//map(0x0008'0000, 0x0008'ffff); // EISA I/O space (64K)
|
||||
//map(0x0009'0000, 0x0009'ffff); // EISA I/O space alias (64K)
|
||||
//map(0x000a'0000, 0x07ff'ffff); // EISA memory (128M)
|
||||
//map(0x0800'0000, 0x17ff'ffff); // physical memory segment 0 (256M)
|
||||
//map(0x1800'0000, 0x1eff'ffff); // reserved (future GIO space) (112M)
|
||||
//map(0x1f00'0000, 0x1f3f'ffff); // graphics system (4M)
|
||||
//map(0x1f40'0000, 0x1f5f'ffff); // gio64 expansion slot 0 (2M)
|
||||
//map(0x1f60'0000, 0x1f9f'ffff); // gio64 expansion slot 1 (4M)
|
||||
//map(0x1fa0'0000, 0x1faf'ffff); // mc registers (1M)
|
||||
//map(0x1fb0'0000, 0x1fbf'ffff); // hpc and i/o devices (1M)
|
||||
//map(0x1fc0'0000, 0x1fff'ffff); // boot prom (4M)
|
||||
//map(0x2000'0000, 0x2fff'ffff); // physical memory segment 1 (256M)
|
||||
//map(0x3000'0000, 0x7fff'ffff); // reserved (1.25G)
|
||||
//map(0x8000'0000, 0xffff'ffff); // EISA memory (2G)
|
||||
|
||||
//map(0x1000'0000, 0x1eff'ffff).lr32([this]() { m_cpu->berr_w(1); return 0; }, "buserror"); // vme
|
||||
|
||||
map(0x1f3f'0000, 0x1f3f'7fff).m(m_gfx, FUNC(sgi_lg1_device::map));
|
||||
|
||||
map(0x1fa0'0000, 0x1fa1'ffff).rw(m_mc, FUNC(sgi_mc_device::read), FUNC(sgi_mc_device::write));
|
||||
|
||||
map(0x1fb8'0000, 0x1fb8'ffff).m(m_hpc, FUNC(hpc1_device::map));
|
||||
map(0x1fb8'0100, 0x1fb8'011f).m(m_eth, FUNC(seeq8003_device::map)).umask32(0xff);
|
||||
map(0x1fb8'0120, 0x1fb8'0127).rw(m_scsi, FUNC(wd33c93a_device::indir_r), FUNC(wd33c93a_device::indir_w)).umask32(0xff00);
|
||||
map(0x1fb8'01c0, 0x1fb8'01ff).m(m_int, FUNC(sgi_int2_device::map)).umask32(0xff);
|
||||
map(0x1fb8'0d00, 0x1fb8'0d0f).rw(m_scc[0], FUNC(scc85c30_device::ab_dc_r), FUNC(scc85c30_device::ab_dc_w)).umask32(0xff);
|
||||
map(0x1fb8'0d10, 0x1fb8'0d1f).rw(m_scc[1], FUNC(scc85c30_device::ab_dc_r), FUNC(scc85c30_device::ab_dc_w)).umask32(0xff);
|
||||
//map(0x1fb8'0d20, 0x1fb8'0d2f).rw(m_scc[2], FUNC(scc85c30_device::ab_dc_r), FUNC(scc85c30_device::ab_dc_w)).umask32(0xff); // V50 only?
|
||||
map(0x1fb8'0d30, 0x1fb8'0d37).noprw(); // TODO: left/right headphone gain mdacs
|
||||
map(0x1fb8'0e00, 0x1fb8'0e7f).rw(m_rtc, FUNC(dp8572a_device::read), FUNC(dp8572a_device::write)).umask32(0xff);
|
||||
map(0x1fbd'0000, 0x1fbd'0003).lr32([]() { return 0x0000'8000; }, "board_rev"); // board revision register
|
||||
|
||||
map(0x1fbe'0000, 0x1fbf'ffff).ram().share("dsp_ram"); // 3xTC55328J-35 (24 bits x 32k)
|
||||
|
||||
map(0x1fc0'0000, 0x1fc7'ffff).rom().region("prom", 0);
|
||||
}
|
||||
|
||||
static void scsi_devices(device_slot_interface &device)
|
||||
{
|
||||
device.option_add("cdrom", NSCSI_CDROM_SGI).machine_config(
|
||||
[](device_t *device)
|
||||
{
|
||||
downcast<nscsi_cdrom_device &>(*device).set_block_size(512);
|
||||
});
|
||||
device.option_add("harddisk", NSCSI_HARDDISK);
|
||||
}
|
||||
|
||||
void ip20_state::indigo_r4000(machine_config &config)
|
||||
{
|
||||
R4000(config, m_cpu, 50'000'000);
|
||||
|
||||
ip20(config);
|
||||
}
|
||||
|
||||
void ip20_state::indigo_r4400(machine_config &config)
|
||||
{
|
||||
R4400(config, m_cpu, 75'000'000);
|
||||
|
||||
ip20(config);
|
||||
}
|
||||
|
||||
void ip20_state::ip20(machine_config &config)
|
||||
{
|
||||
m_cpu->set_addrmap(AS_PROGRAM, &ip20_state::cpu_map);
|
||||
|
||||
EEPROM_93C56_16BIT(config, m_eerom);
|
||||
|
||||
SGI_MC(config, m_mc, m_cpu, m_eerom, 50'000'000);
|
||||
m_mc->eisa_present().set_constant(0);
|
||||
|
||||
SGI_HPC1(config, m_hpc, 0);
|
||||
m_hpc->set_gio(m_cpu, AS_PROGRAM);
|
||||
m_hpc->set_enet(m_eth);
|
||||
m_hpc->int_w().set(m_int, FUNC(sgi_int2_device::lio0_w<sgi_int2_device::LIO0_ETHERNET>));
|
||||
m_hpc->dma_r_cb<0>().set(m_scsi, FUNC(wd33c93a_device::dma_r));
|
||||
m_hpc->dma_w_cb<0>().set(m_scsi, FUNC(wd33c93a_device::dma_w));
|
||||
m_hpc->eeprom_dati().set(m_nvram, FUNC(eeprom_serial_93cxx_device::do_read));
|
||||
m_hpc->eeprom_out().set(
|
||||
[this](u8 data)
|
||||
{
|
||||
// TODO: bit 0 console led
|
||||
m_nvram->di_write(BIT(data, 3));
|
||||
m_nvram->cs_write(BIT(data, 1));
|
||||
m_nvram->clk_write(BIT(data, 2));
|
||||
});
|
||||
|
||||
SGI_INT2(config, m_int, 10_MHz_XTAL);
|
||||
m_int->write_intr<1>().set_inputline(m_cpu, INPUT_LINE_IRQ1);
|
||||
m_int->write_intr<2>().set_inputline(m_cpu, INPUT_LINE_IRQ2);
|
||||
m_int->write_intr<3>().set_inputline(m_cpu, INPUT_LINE_IRQ3);
|
||||
m_int->write_intr<4>().set_inputline(m_cpu, INPUT_LINE_IRQ4);
|
||||
m_int->write_intr<5>().set_inputline(m_cpu, INPUT_LINE_IRQ5);
|
||||
// TODO: write_led and write_poweroff outputs
|
||||
//
|
||||
// 0 cache parity error?
|
||||
// 1 1Hz heartbeat
|
||||
// 2 off when cpu is idle
|
||||
// 3 graphics
|
||||
// 4 poweroff?
|
||||
|
||||
EEPROM_93C56_16BIT(config, m_nvram);
|
||||
|
||||
DP8572A(config, m_rtc, 32.768_kHz_XTAL).set_use_utc(true);
|
||||
|
||||
NSCSI_BUS(config, "scsi", 0);
|
||||
NSCSI_CONNECTOR(config, "scsi:0").option_set("wd33c93a", WD33C93A).machine_config(
|
||||
[this](device_t *device)
|
||||
{
|
||||
wd33c93a_device &scsi = downcast<wd33c93a_device &>(*device);
|
||||
|
||||
scsi.set_clock(10_MHz_XTAL);
|
||||
scsi.irq_cb().set(m_int, FUNC(sgi_int2_device::lio0_w<sgi_int2_device::LIO0_SCSI>));
|
||||
scsi.drq_cb().set(m_hpc, FUNC(hpc1_device::write_drq<0>));
|
||||
});
|
||||
NSCSI_CONNECTOR(config, "scsi:1", scsi_devices, "harddisk", false);
|
||||
NSCSI_CONNECTOR(config, "scsi:2", scsi_devices, nullptr, false);
|
||||
NSCSI_CONNECTOR(config, "scsi:3", scsi_devices, nullptr, false);
|
||||
NSCSI_CONNECTOR(config, "scsi:4", scsi_devices, "cdrom", false);
|
||||
NSCSI_CONNECTOR(config, "scsi:5", scsi_devices, nullptr, false);
|
||||
NSCSI_CONNECTOR(config, "scsi:6", scsi_devices, nullptr, false);
|
||||
NSCSI_CONNECTOR(config, "scsi:7", scsi_devices, nullptr, false);
|
||||
|
||||
SEEQ8003(config, m_eth, 0);
|
||||
m_eth->out_int_cb().set(m_hpc, FUNC(hpc1_device::write_int));
|
||||
m_eth->out_rxrdy_cb().set(m_hpc, FUNC(hpc1_device::write_drq<1>));
|
||||
m_hpc->dma_r_cb<1>().set(m_eth, FUNC(seeq8003_device::fifo_r));
|
||||
m_hpc->dma_w_cb<1>().set(m_eth, FUNC(seeq8003_device::fifo_w));
|
||||
|
||||
input_merger_any_high_device &scc_irq(INPUT_MERGER_ANY_HIGH(config, "scc_irq"));
|
||||
scc_irq.output_handler().set(m_int, FUNC(sgi_int2_device::lio0_w<sgi_int2_device::LIO0_DUART>));
|
||||
|
||||
// duart 0
|
||||
SCC85C30(config, m_scc[0], 10_MHz_XTAL);
|
||||
m_scc[0]->configure_channels(3'686'400, 0, 3'686'400, 0);
|
||||
m_scc[0]->out_int_callback().set(scc_irq, FUNC(input_merger_any_high_device::in_w<0>));
|
||||
|
||||
sgi_kbd_port_device &kbd_port(SGI_KBD_PORT(config, "keyboard_port"));
|
||||
kbd_port.option_set("keyboard", SGI_KBD);
|
||||
rs232_port_device &mouse_port(RS232_PORT(config, "mouse_port", 0));
|
||||
mouse_port.option_set("mouse", SGI_HLE_SERIAL_MOUSE);
|
||||
m_scc[0]->out_txda_callback().set(kbd_port, FUNC(sgi_kbd_port_device::write_txd));
|
||||
kbd_port.rxd_handler().set(m_scc[0], FUNC(scc85c30_device::rxa_w));
|
||||
mouse_port.rxd_handler().set(m_scc[0], FUNC(scc85c30_device::rxb_w));
|
||||
|
||||
// duart 1
|
||||
SCC85C30(config, m_scc[1], 10_MHz_XTAL);
|
||||
m_scc[1]->configure_channels(3'686'400, 0, 3'686'400, 0);
|
||||
m_scc[1]->out_int_callback().set(scc_irq, FUNC(input_merger_any_high_device::in_w<1>));
|
||||
|
||||
rs232_port_device &rs232a(RS232_PORT(config, "rs232a", default_rs232_devices, nullptr));
|
||||
rs232_port_device &rs232b(RS232_PORT(config, "rs232b", default_rs232_devices, nullptr));
|
||||
m_scc[1]->out_txda_callback().set(rs232a, FUNC(rs232_port_device::write_txd));
|
||||
m_scc[1]->out_dtra_callback().set(rs232a, FUNC(rs232_port_device::write_dtr));
|
||||
m_scc[1]->out_rtsa_callback().set(rs232a, FUNC(rs232_port_device::write_rts));
|
||||
m_scc[1]->out_txdb_callback().set(rs232b, FUNC(rs232_port_device::write_txd));
|
||||
m_scc[1]->out_dtrb_callback().set(rs232b, FUNC(rs232_port_device::write_dtr));
|
||||
m_scc[1]->out_rtsb_callback().set(rs232b, FUNC(rs232_port_device::write_rts));
|
||||
rs232a.cts_handler().set(m_scc[1], FUNC(scc85c30_device::ctsa_w));
|
||||
rs232a.dcd_handler().set(m_scc[1], FUNC(scc85c30_device::dcda_w));
|
||||
rs232a.rxd_handler().set(m_scc[1], FUNC(scc85c30_device::rxa_w));
|
||||
rs232b.cts_handler().set(m_scc[1], FUNC(scc85c30_device::ctsb_w));
|
||||
rs232b.dcd_handler().set(m_scc[1], FUNC(scc85c30_device::dcdb_w));
|
||||
rs232b.rxd_handler().set(m_scc[1], FUNC(scc85c30_device::rxb_w));
|
||||
|
||||
// duart 2
|
||||
SCC85C30(config, m_scc[2], 10_MHz_XTAL);
|
||||
m_scc[2]->configure_channels(3'686'400, 0, 3'686'400, 0);
|
||||
m_scc[2]->out_int_callback().set(scc_irq, FUNC(input_merger_any_high_device::in_w<2>));
|
||||
|
||||
DSP56001(config, m_dsp, 20_MHz_XTAL);
|
||||
|
||||
SGI_LG1(config, m_gfx);
|
||||
m_gfx->write_vblank().set(m_int, FUNC(sgi_int2_device::lio1_w<sgi_int2_device::LIO1_GIO2>));
|
||||
}
|
||||
|
||||
ROM_START(indigo_r4000)
|
||||
ROM_REGION64_BE(0x80000, "prom", 0)
|
||||
ROMX_LOAD("ip20prom.070-8116-004.bin", 0x000000, 0x080000, CRC(940d960e) SHA1(596aba530b53a147985ff3f6f853471ce48c866c), ROM_GROUPDWORD | ROM_REVERSE)
|
||||
ROM_END
|
||||
|
||||
#define rom_indigo_r4400 rom_indigo_r4000
|
||||
} // anonymous namespace
|
||||
|
||||
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
|
||||
COMP(1992, indigo_r4000, 0, 0, indigo_r4000, 0, ip20_state, empty_init, "Silicon Graphics", "IRIS Indigo R4000", MACHINE_NO_SOUND | MACHINE_IMPERFECT_GRAPHICS)
|
||||
COMP(1991, indigo_r4400, 0, 0, indigo_r4400, 0, ip20_state, empty_init, "Silicon Graphics", "IRIS Indigo R4400", MACHINE_NO_SOUND | MACHINE_IMPERFECT_GRAPHICS)
|
@ -1,27 +1,23 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Patrick Mackinlay
|
||||
/*
|
||||
* SGI Personal IRIS family driver
|
||||
* Silicon Graphics Personal IRIS 4D/20 and 4D/25.
|
||||
*
|
||||
* Year Model Board Type CPU Clock I/D Cache Code Name
|
||||
* 1988 4D/20 IP6 IP6 R2000 12.5MHz 16KiB/8KiB Eclipse
|
||||
* 1989 4D/25 IP10 IP6 R3000 20MHz 64KiB/32KiB Eclipse
|
||||
* 1991 4D/30 IP14 IP12 R3000 30MHz 64KiB/64KiB Magnum
|
||||
* 1991 4D/35 IP12 IP12 R3000 36MHz 64KiB/64KiB Magnum
|
||||
*
|
||||
* Sources:
|
||||
* - http://bitsavers.org/pdf/sgi/personal_iris/VME-Eclipse_CPU_VIP10_Specification.pdf
|
||||
* - http://www.bitsavers.org/pdf/sgi/personal_iris/SGI_IP-6_Schematic.pdf
|
||||
* - VME-Eclipse CPU (VIP10) Specification, Silicon Graphics, Inc.
|
||||
* - SGI IP-6 Schematic
|
||||
* - http://www.futuretech.blinkenlights.nl/pitechrep.html
|
||||
* - https://hardware.majix.org/computers/sgi.pi/index.shtml
|
||||
* - http://archive.irix.cc/sgistuff/hardware/systems/personal.html
|
||||
* - http://archive.irix.cc/developerforum95/Silicon_Graphics_Developer_Forum_95_The_CD_Volume_2/documents/hw_handbook_html/handbook.html
|
||||
* - https://github.com/NetBSD/src/tree/trunk/sys/arch/sgimips/
|
||||
*
|
||||
* TODO:
|
||||
* - audio, printer
|
||||
* - devicify ioc1 and ctl1
|
||||
* - 4d30/35 skeleton only
|
||||
*
|
||||
* Status:
|
||||
* - parity and cache diagnostics fail
|
||||
@ -32,6 +28,15 @@
|
||||
* - fpu (cvt.?.? invalid operation exceptions)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Installation instructions
|
||||
* --
|
||||
* 1. boot, enter monitor, set ethernet address: eaddr 08:00:69:12:34:56
|
||||
* 2. start mame with CDROM iso image as hard disk ID 6: mame 4d20 ... -scsi:6 harddisk -hard2 pathname.iso
|
||||
* 3. boot, enter monitor, launch sash: boot -f dksc(0,6,8)sash.IP6
|
||||
* 4.
|
||||
*/
|
||||
|
||||
#include "emu.h"
|
||||
|
||||
// cpu and memory
|
||||
@ -71,10 +76,10 @@
|
||||
|
||||
namespace {
|
||||
|
||||
class pi4d2x_state : public driver_device
|
||||
class ip6_state : public driver_device
|
||||
{
|
||||
public:
|
||||
pi4d2x_state(machine_config const &mconfig, device_type type, char const *tag)
|
||||
ip6_state(machine_config const &mconfig, device_type type, char const *tag)
|
||||
: driver_device(mconfig, type, tag)
|
||||
, m_cpu(*this, "maincpu")
|
||||
, m_ram(*this, "ram")
|
||||
@ -233,66 +238,13 @@ private:
|
||||
u16 m_gdma_buflen = 0; // buffer length
|
||||
};
|
||||
|
||||
class pi4d3x_state : public driver_device
|
||||
{
|
||||
public:
|
||||
pi4d3x_state(machine_config const &mconfig, device_type type, char const *tag)
|
||||
: driver_device(mconfig, type, tag)
|
||||
, m_cpu(*this, "maincpu")
|
||||
, m_ram(*this, "ram")
|
||||
, m_eprom(*this, "boot")
|
||||
, m_eeprom(*this, "eeprom")
|
||||
, m_rtc(*this, "rtc")
|
||||
, m_pit(*this, "pit")
|
||||
, m_scsi(*this, "scsi:0:wd33c93a")
|
||||
, m_enet(*this, "enet")
|
||||
, m_duart(*this, "duart%u", 0U)
|
||||
, m_serial(*this, "serial%u", 1U)
|
||||
, m_dsp(*this, "dsp")
|
||||
{
|
||||
std::fill(std::begin(m_lio_isr), std::end(m_lio_isr), 0 );
|
||||
}
|
||||
|
||||
void pi4d30(machine_config &config);
|
||||
void pi4d35(machine_config &config);
|
||||
|
||||
void initialize();
|
||||
|
||||
private:
|
||||
required_device<mips1_device_base> m_cpu;
|
||||
required_device<ram_device> m_ram;
|
||||
required_region_ptr<u16> m_eprom;
|
||||
required_device<eeprom_serial_93c56_16bit_device> m_eeprom;
|
||||
|
||||
required_device<dp8572a_device> m_rtc;
|
||||
required_device<pit8254_device> m_pit;
|
||||
required_device<wd33c9x_base_device> m_scsi;
|
||||
required_device<seeq8003_device> m_enet;
|
||||
required_device_array<z80scc_device, 3> m_duart;
|
||||
required_device_array<rs232_port_device, 4> m_serial;
|
||||
required_device<dsp56001_device> m_dsp;
|
||||
|
||||
void common(machine_config &config);
|
||||
void map(address_map &map);
|
||||
|
||||
template <unsigned LIO, unsigned N> void lio_interrupt(int state) { lio_interrupt(LIO, N, state); }
|
||||
void lio_interrupt(unsigned const lio, unsigned const number, int state);
|
||||
|
||||
u8 m_lio_isr[2];
|
||||
u8 m_lio_imr[2];
|
||||
bool m_lio_int[2];
|
||||
|
||||
//u8 m_sysid = 1; // FPPRES
|
||||
u8 m_cpuauxctl = 0;
|
||||
};
|
||||
|
||||
void pi4d2x_state::map(address_map &map)
|
||||
void ip6_state::map(address_map &map)
|
||||
{
|
||||
// silence local memory
|
||||
map(0x00000000, 0x0fffffff).noprw();
|
||||
|
||||
// vme address space produces bus errors by default
|
||||
map(0x10000000, 0x1effffff).rw(FUNC(pi4d2x_state::buserror_r), FUNC(pi4d2x_state::buserror_w));
|
||||
map(0x10000000, 0x1effffff).rw(FUNC(ip6_state::buserror_r), FUNC(ip6_state::buserror_w));
|
||||
|
||||
// TODO: 1 32-bit 6U VME slot
|
||||
//map(0x10000000, 0x1bffffff); // vme a32 modifier 0x09 non-privileged
|
||||
@ -306,7 +258,7 @@ void pi4d2x_state::map(address_map &map)
|
||||
map(0x1f000000, 0x1f007fff).m(m_gfx, FUNC(sgi_gr1_device::map)).mirror(0x8000);
|
||||
|
||||
map(0x1f800000, 0x1f800003).lrw8(NAME([this]() { return m_memcfg; }), NAME([this](u8 data) { m_memcfg = data; })).umask32(0xff000000);
|
||||
map(0x1f800000, 0x1f800003).r(FUNC(pi4d2x_state::sysid_r)).umask32(0x00ff0000);
|
||||
map(0x1f800000, 0x1f800003).r(FUNC(ip6_state::sysid_r)).umask32(0x00ff0000);
|
||||
|
||||
map(0x1f840000, 0x1f840003).lrw8(NAME([this]() { return m_vme_isr; }), NAME([this](u8 data) { m_vme_isr = data; })).umask32(0x000000ff);
|
||||
map(0x1f840008, 0x1f84000b).lrw8(NAME([this]() { return m_vme_imr; }), NAME([this](u8 data) { m_vme_imr = data; })).umask32(0x000000ff);
|
||||
@ -479,7 +431,7 @@ void pi4d2x_state::map(address_map &map)
|
||||
map(0x1fa80008, 0x1fa8000b).lr8([]() { return 0; }, "scsibstat").umask32(0x00ff0000);
|
||||
|
||||
// TODO: IOC2 configuration register, bus error on IOC1
|
||||
//map(0x1fa80008, 0x1fa8000b).rw(FUNC(pi4d2x_state::buserror_r), FUNC(pi4d2x_state::buserror_w));
|
||||
//map(0x1fa80008, 0x1fa8000b).rw(FUNC(ip6_state::buserror_r), FUNC(ip6_state::buserror_w));
|
||||
|
||||
map(0x1faa0000, 0x1faa0003).lrw8([this](offs_t offset) { m_parerr &= ~(PARERR_BYTE | (1 << offset)); return 0; }, "clrerr_r", [this](offs_t offset) { m_parerr &= ~(PARERR_BYTE | (1 << offset)); }, "clrerr_w");
|
||||
map(0x1faa0004, 0x1faa0007).lr8(NAME([this]() { return m_parerr; })).umask32(0x00ff0000);
|
||||
@ -500,110 +452,7 @@ void pi4d2x_state::map(address_map &map)
|
||||
map(0x1fc00000, 0x1fc3ffff).rom().region("boot", 0);
|
||||
|
||||
// unused memory address space produces bus errors
|
||||
map(0x40000000, 0xffffffff).rw(FUNC(pi4d2x_state::buserror_r), FUNC(pi4d2x_state::buserror_w));
|
||||
}
|
||||
|
||||
void pi4d3x_state::map(address_map &map)
|
||||
{
|
||||
|
||||
//map(0x1fa00000, 0x1fa00003).noprw().umask32(0xffff0000); // CPUCTRL
|
||||
// RSTCONFIG
|
||||
//map(0x1fa00008, 0x1fa0000b).lr8([this](){ return m_sysid; }, "sysid").umask32(0xff000000);
|
||||
// MEMCFG0
|
||||
// MEMCFG1
|
||||
// REFTIM
|
||||
// PARERR
|
||||
//map(0x1fa10210, 0x1fa10213).nopw(); // CLERERR
|
||||
|
||||
map(0x1fb80000, 0x1fb800bf).ram(); // FIXME: stub out ethernet, scsi and parallel registers
|
||||
|
||||
map(0x1fb80100, 0x1fb8011f).m(m_enet, FUNC(seeq8003_device::map)).umask32(0x000000ff);
|
||||
|
||||
map(0x1fb80120, 0x1fb80123).rw(m_scsi, FUNC(wd33c93_device::indir_addr_r), FUNC(wd33c93_device::indir_addr_w)).umask32(0x0000ff00);
|
||||
map(0x1fb80124, 0x1fb80127).rw(m_scsi, FUNC(wd33c93_device::indir_reg_r), FUNC(wd33c93_device::indir_reg_w)).umask32(0x0000ff00);
|
||||
|
||||
map(0x1fb80180, 0x1fb801bb).ram(); // FIXME: stub out pbus registers
|
||||
map(0x1fb801bc, 0x1fb801bf).lrw8(
|
||||
[this]()
|
||||
{
|
||||
u8 data = m_cpuauxctl & ~0x10;
|
||||
|
||||
// serial eeprom data in
|
||||
if (m_eeprom->do_read())
|
||||
data |= 0x10;
|
||||
|
||||
return data;
|
||||
}, "cpu_aux_ctrl_r",
|
||||
[this](u8 data)
|
||||
{
|
||||
// console LED / protection register enable (PRE)
|
||||
//m_leds[LED_CON] = BIT(data, 0);
|
||||
|
||||
// serial eeprom chip select, clock and data out
|
||||
m_eeprom->cs_write(BIT(data, 1));
|
||||
m_eeprom->clk_write(BIT(data, 2));
|
||||
m_eeprom->di_write(BIT(data, 3));
|
||||
|
||||
m_cpuauxctl = data;
|
||||
}, "cpu_aux_ctrl_w").umask32(0x000000ff);
|
||||
|
||||
map(0x1fb801c0, 0x1fb801c3).lr8(NAME([this]() { return m_lio_isr[0]; })).umask32(0x000000ff);
|
||||
map(0x1fb801c4, 0x1fb801c7).lrw8(
|
||||
NAME([this]() { return m_lio_imr[0]; }),
|
||||
[this](u8 data)
|
||||
{
|
||||
m_lio_imr[0] = data;
|
||||
|
||||
// update interrupt line
|
||||
bool const lio_int = m_lio_isr[0] & m_lio_imr[0];
|
||||
if (m_lio_int[0] ^ lio_int)
|
||||
{
|
||||
m_lio_int[0] = lio_int;
|
||||
m_cpu->set_input_line(INPUT_LINE_IRQ1, lio_int);
|
||||
}
|
||||
}, "lio0_imr_w").umask32(0x000000ff);
|
||||
|
||||
map(0x1fb801c8, 0x1fb801cb).lr8(NAME([this]() { return m_lio_isr[1]; })).umask32(0x000000ff);
|
||||
map(0x1fb801cc, 0x1fb801cf).lrw8(
|
||||
NAME([this]() { return m_lio_imr[1]; }),
|
||||
[this](u8 data)
|
||||
{
|
||||
m_lio_imr[1] = data;
|
||||
|
||||
// update interrupt line
|
||||
bool const lio_int = m_lio_isr[1] & m_lio_imr[1];
|
||||
if (m_lio_int[1] ^ lio_int)
|
||||
{
|
||||
m_lio_int[1] = lio_int;
|
||||
m_cpu->set_input_line(INPUT_LINE_IRQ2, lio_int);
|
||||
}
|
||||
}, "lio1_imr_w").umask32(0x000000ff);
|
||||
|
||||
map(0x1fb801d0, 0x1fb801df).ram(); // FIXME: stub out int2 registers
|
||||
map(0x1fb801e0, 0x1fb801e3).lw8(
|
||||
[this](u8 data)
|
||||
{
|
||||
// timer 0 acknowledge
|
||||
if (BIT(data, 0))
|
||||
m_cpu->set_input_line(INPUT_LINE_IRQ3, 0);
|
||||
|
||||
// timer 1 acknowledge
|
||||
if (BIT(data, 1))
|
||||
m_cpu->set_input_line(INPUT_LINE_IRQ4, 0);
|
||||
}, "timer_ack").umask32(0x000000ff);
|
||||
map(0x1fb801f0, 0x1fb801ff).rw(m_pit, FUNC(pit8254_device::read), FUNC(pit8254_device::write)).umask32(0x000000ff);
|
||||
|
||||
map(0x1fb80d00, 0x1fb80d0f).rw(m_duart[0], FUNC(z80scc_device::ab_dc_r), FUNC(z80scc_device::ab_dc_w)).umask32(0x000000ff);
|
||||
map(0x1fb80d10, 0x1fb80d1f).rw(m_duart[1], FUNC(z80scc_device::ab_dc_r), FUNC(z80scc_device::ab_dc_w)).umask32(0x000000ff);
|
||||
map(0x1fb80d20, 0x1fb80d2f).rw(m_duart[2], FUNC(z80scc_device::ab_dc_r), FUNC(z80scc_device::ab_dc_w)).umask32(0x000000ff);
|
||||
|
||||
map(0x1fb80e00, 0x1fb80e7f).rw(m_rtc, FUNC(dp8572a_device::read), FUNC(dp8572a_device::write)).umask32(0x000000ff);
|
||||
|
||||
map(0x1fbe0000, 0x1fbfffff).ram().share("dsp_sram"); // 3xTC55328J-25 32KiB CMOS static RAM
|
||||
|
||||
map(0x1fbd0000, 0x1fbd0003).nopr(); // FIXME: board revision register
|
||||
|
||||
map(0x1fc00000, 0x1fc7ffff).lr16([this](offs_t offset) { return m_eprom[offset]; }, "boot");
|
||||
map(0x40000000, 0xffffffff).rw(FUNC(ip6_state::buserror_r), FUNC(ip6_state::buserror_w));
|
||||
}
|
||||
|
||||
static void scsi_devices(device_slot_interface &device)
|
||||
@ -616,7 +465,7 @@ static void scsi_devices(device_slot_interface &device)
|
||||
device.option_add("harddisk", NSCSI_HARDDISK);
|
||||
}
|
||||
|
||||
void pi4d2x_state::pi4d20(machine_config &config)
|
||||
void ip6_state::pi4d20(machine_config &config)
|
||||
{
|
||||
R3000(config, m_cpu, 25_MHz_XTAL / 2, 16384, 8192);
|
||||
m_cpu->set_fpu(mips1_device_base::MIPS_R3010);
|
||||
@ -624,7 +473,7 @@ void pi4d2x_state::pi4d20(machine_config &config)
|
||||
common(config);
|
||||
}
|
||||
|
||||
void pi4d2x_state::pi4d25(machine_config &config)
|
||||
void ip6_state::pi4d25(machine_config &config)
|
||||
{
|
||||
R3000(config, m_cpu, 20_MHz_XTAL, 32768, 65536);
|
||||
m_cpu->set_fpu(mips1_device_base::MIPS_R3010);
|
||||
@ -632,26 +481,9 @@ void pi4d2x_state::pi4d25(machine_config &config)
|
||||
common(config);
|
||||
}
|
||||
|
||||
void pi4d3x_state::pi4d30(machine_config &config)
|
||||
void ip6_state::common(machine_config &config)
|
||||
{
|
||||
R3000A(config, m_cpu, 30_MHz_XTAL, 65536, 65536);
|
||||
m_cpu->set_fpu(mips1_device_base::MIPS_R3010A);
|
||||
|
||||
common(config);
|
||||
}
|
||||
|
||||
void pi4d3x_state::pi4d35(machine_config &config)
|
||||
{
|
||||
R3000A(config, m_cpu, 36_MHz_XTAL, 65536, 65536);
|
||||
m_cpu->set_fpu(mips1_device_base::MIPS_R3010A);
|
||||
|
||||
common(config);
|
||||
}
|
||||
|
||||
void pi4d2x_state::common(machine_config &config)
|
||||
{
|
||||
m_cpu->set_endianness(ENDIANNESS_BIG);
|
||||
m_cpu->set_addrmap(AS_PROGRAM, &pi4d2x_state::map);
|
||||
m_cpu->set_addrmap(AS_PROGRAM, &ip6_state::map);
|
||||
m_cpu->in_brcond<0>().set([]() { return 1; }); // writeback complete
|
||||
|
||||
// 16 SIMM slots with 1, 2? or 4MB SIMMs installed in sets of 4
|
||||
@ -678,8 +510,8 @@ void pi4d2x_state::common(machine_config &config)
|
||||
wd33c9x_base_device &wd33c93(downcast<wd33c9x_base_device &>(*device));
|
||||
|
||||
wd33c93.set_clock(10000000);
|
||||
wd33c93.irq_cb().set(*this, FUNC(pi4d2x_state::lio_interrupt<LIO_SCSI>)).invert();
|
||||
wd33c93.drq_cb().set(*this, FUNC(pi4d2x_state::scsi_drq));
|
||||
wd33c93.irq_cb().set(*this, FUNC(ip6_state::lio_interrupt<LIO_SCSI>)).invert();
|
||||
wd33c93.drq_cb().set(*this, FUNC(ip6_state::scsi_drq));
|
||||
});
|
||||
NSCSI_CONNECTOR(config, "scsi:1", scsi_devices, "harddisk", false);
|
||||
NSCSI_CONNECTOR(config, "scsi:2", scsi_devices, nullptr, false);
|
||||
@ -690,7 +522,7 @@ void pi4d2x_state::common(machine_config &config)
|
||||
NSCSI_CONNECTOR(config, "scsi:7", scsi_devices, nullptr, false);
|
||||
|
||||
AM7990(config, m_enet);
|
||||
m_enet->intr_out().set(FUNC(pi4d2x_state::lio_interrupt<LIO_ENET>));
|
||||
m_enet->intr_out().set(FUNC(ip6_state::lio_interrupt<LIO_ENET>));
|
||||
m_enet->dma_in().set(
|
||||
[this](offs_t offset)
|
||||
{
|
||||
@ -719,7 +551,7 @@ void pi4d2x_state::common(machine_config &config)
|
||||
"mouse"));
|
||||
|
||||
// duart 0 outputs
|
||||
m_duart[0]->irq_cb().set(FUNC(pi4d2x_state::lio_interrupt<LIO_D0>)).invert();
|
||||
m_duart[0]->irq_cb().set(FUNC(ip6_state::lio_interrupt<LIO_D0>)).invert();
|
||||
m_duart[0]->a_tx_cb().set(keyboard_port, FUNC(sgi_kbd_port_device::write_txd));
|
||||
m_duart[0]->b_tx_cb().set(mouse_port, FUNC(rs232_port_device::write_txd));
|
||||
|
||||
@ -733,7 +565,7 @@ void pi4d2x_state::common(machine_config &config)
|
||||
RS232_PORT(config, m_serial[1], default_rs232_devices, nullptr);
|
||||
|
||||
// duart 1 outputs
|
||||
m_duart[1]->irq_cb().set(FUNC(pi4d2x_state::lio_interrupt<LIO_D1>)).invert();
|
||||
m_duart[1]->irq_cb().set(FUNC(ip6_state::lio_interrupt<LIO_D1>)).invert();
|
||||
m_duart[1]->a_tx_cb().set(m_serial[0], FUNC(rs232_port_device::write_txd));
|
||||
m_duart[1]->b_tx_cb().set(m_serial[1], FUNC(rs232_port_device::write_txd));
|
||||
m_duart[1]->outport_cb().set(
|
||||
@ -769,8 +601,8 @@ void pi4d2x_state::common(machine_config &config)
|
||||
else
|
||||
m_lio_isr |= (1U << LIO_VRSTAT);
|
||||
});
|
||||
m_gfx->out_int().set(*this, FUNC(pi4d2x_state::lio_interrupt<LIO_GE>)).invert();
|
||||
m_gfx->out_int_fifo().set(*this, FUNC(pi4d2x_state::lio_interrupt<LIO_FIFO>)).invert();
|
||||
m_gfx->out_int().set(*this, FUNC(ip6_state::lio_interrupt<LIO_GE>)).invert();
|
||||
m_gfx->out_int_fifo().set(*this, FUNC(ip6_state::lio_interrupt<LIO_FIFO>)).invert();
|
||||
|
||||
// TODO: vme slot, cpu interrupt 0
|
||||
|
||||
@ -779,125 +611,7 @@ void pi4d2x_state::common(machine_config &config)
|
||||
config.set_default_layout(layout_4dpi);
|
||||
}
|
||||
|
||||
void pi4d3x_state::common(machine_config &config)
|
||||
{
|
||||
m_cpu->set_endianness(ENDIANNESS_BIG);
|
||||
m_cpu->set_addrmap(AS_PROGRAM, &pi4d3x_state::map);
|
||||
m_cpu->in_brcond<0>().set([]() { return 1; }); // writeback complete
|
||||
|
||||
RAM(config, m_ram);
|
||||
m_ram->set_default_size("16M");
|
||||
m_ram->set_extra_options("8M,32M,64M,128M");
|
||||
m_ram->set_default_value(0);
|
||||
|
||||
EEPROM_93C56_16BIT(config, m_eeprom);
|
||||
|
||||
DP8572A(config, m_rtc, 32.768_kHz_XTAL);
|
||||
|
||||
// 1: local0
|
||||
// 2: local1
|
||||
// 3: 8254.0
|
||||
// 4: 8254.1
|
||||
// int 7, 11 -> mappable?
|
||||
// level < 8 -> local0
|
||||
// level < 16 -> local1
|
||||
// level < 24 -> map0
|
||||
// level < 32 -> map1
|
||||
|
||||
// FIXME: part of INT2 asic
|
||||
PIT8254(config, m_pit);
|
||||
m_pit->set_clk<2>(1_MHz_XTAL);
|
||||
m_pit->out_handler<0>().set([this](int state) { if (state) m_cpu->set_input_line(INPUT_LINE_IRQ3, 1); });
|
||||
m_pit->out_handler<1>().set([this](int state) { if (state) m_cpu->set_input_line(INPUT_LINE_IRQ4, 1); });
|
||||
m_pit->out_handler<2>().set(m_pit, FUNC(pit8254_device::write_clk0));
|
||||
m_pit->out_handler<2>().append(m_pit, FUNC(pit8254_device::write_clk1));
|
||||
|
||||
NSCSI_BUS(config, "scsi");
|
||||
NSCSI_CONNECTOR(config, "scsi:0").option_set("wd33c93a", WD33C93A).machine_config(
|
||||
[this](device_t *device)
|
||||
{
|
||||
wd33c9x_base_device &wd33c93(downcast<wd33c9x_base_device &>(*device));
|
||||
|
||||
wd33c93.set_clock(10'000'000);
|
||||
wd33c93.irq_cb().set(*this, &pi4d3x_state::lio_interrupt<0, 2>, "lio0.2");
|
||||
//wd33c93.drq_cb().set(*this, FUNC(pi4d2x_state::scsi_drq));
|
||||
});
|
||||
NSCSI_CONNECTOR(config, "scsi:1", scsi_devices, "harddisk", false);
|
||||
NSCSI_CONNECTOR(config, "scsi:2", scsi_devices, nullptr, false);
|
||||
NSCSI_CONNECTOR(config, "scsi:3", scsi_devices, nullptr, false);
|
||||
NSCSI_CONNECTOR(config, "scsi:4", scsi_devices, nullptr, false);
|
||||
NSCSI_CONNECTOR(config, "scsi:5", scsi_devices, nullptr, false);
|
||||
NSCSI_CONNECTOR(config, "scsi:6", scsi_devices, nullptr, false);
|
||||
NSCSI_CONNECTOR(config, "scsi:7", scsi_devices, nullptr, false);
|
||||
|
||||
SEEQ8003(config, m_enet, 0);
|
||||
m_enet->out_int_cb().set(&pi4d3x_state::lio_interrupt<0, 3>, "lio0.3");
|
||||
|
||||
input_merger_device &duart_int(INPUT_MERGER_ANY_HIGH(config, "duart_int"));
|
||||
duart_int.output_handler().set(&pi4d3x_state::lio_interrupt<0, 5>, "lio0.5");
|
||||
|
||||
// duart 0: keyboard/mouse
|
||||
SCC85C30(config, m_duart[0], 10_MHz_XTAL); // Z8513010VSC ESCC
|
||||
m_duart[0]->out_int_callback().set(duart_int, FUNC(input_merger_device::in_w<0>));
|
||||
|
||||
// keyboard
|
||||
sgi_kbd_port_device &keyboard_port(SGI_KBD_PORT(config, "keyboard_port", default_sgi_kbd_devices, "keyboard"));
|
||||
m_duart[0]->out_txdb_callback().set(keyboard_port, FUNC(sgi_kbd_port_device::write_txd));
|
||||
keyboard_port.rxd_handler().set(m_duart[0], FUNC(z80scc_device::rxb_w));
|
||||
|
||||
// mouse
|
||||
rs232_port_device &mouse_port(RS232_PORT(config, "mouse_port",
|
||||
[](device_slot_interface &device)
|
||||
{
|
||||
device.option_add("mouse", SGI_HLE_SERIAL_MOUSE);
|
||||
},
|
||||
"mouse"));
|
||||
m_duart[0]->out_txda_callback().set(mouse_port, FUNC(rs232_port_device::write_txd));
|
||||
mouse_port.rxd_handler().set(m_duart[0], FUNC(z80scc_device::rxa_w));
|
||||
|
||||
// duart 1: serial ports
|
||||
SCC85C30(config, m_duart[1], 10_MHz_XTAL); // Z8513010VSC ESCC
|
||||
m_duart[1]->configure_channels(3'686'400, 0, 3'686'400, 0);
|
||||
m_duart[1]->out_int_callback().set(duart_int, FUNC(input_merger_device::in_w<1>));
|
||||
|
||||
// serial port 1
|
||||
RS232_PORT(config, m_serial[0], default_rs232_devices, nullptr);
|
||||
m_duart[1]->out_dtra_callback().set(m_serial[0], FUNC(rs232_port_device::write_dtr));
|
||||
m_duart[1]->out_rtsa_callback().set(m_serial[0], FUNC(rs232_port_device::write_rts));
|
||||
m_duart[1]->out_txda_callback().set(m_serial[0], FUNC(rs232_port_device::write_txd));
|
||||
m_serial[0]->cts_handler().set(m_duart[1], FUNC(z80scc_device::ctsa_w));
|
||||
m_serial[0]->dcd_handler().set(m_duart[1], FUNC(z80scc_device::dcda_w));
|
||||
m_serial[0]->rxd_handler().set(m_duart[1], FUNC(z80scc_device::rxa_w));
|
||||
|
||||
// serial port 2
|
||||
RS232_PORT(config, m_serial[1], default_rs232_devices, "terminal");
|
||||
m_duart[1]->out_dtrb_callback().set(m_serial[1], FUNC(rs232_port_device::write_dtr));
|
||||
m_duart[1]->out_rtsb_callback().set(m_serial[1], FUNC(rs232_port_device::write_rts));
|
||||
m_duart[1]->out_txdb_callback().set(m_serial[1], FUNC(rs232_port_device::write_txd));
|
||||
m_serial[1]->cts_handler().set(m_duart[1], FUNC(z80scc_device::ctsb_w));
|
||||
m_serial[1]->dcd_handler().set(m_duart[1], FUNC(z80scc_device::dcdb_w));
|
||||
m_serial[1]->rxd_handler().set(m_duart[1], FUNC(z80scc_device::rxb_w));
|
||||
|
||||
// duart 2: "Apple" RS-422 serial ports
|
||||
SCC85C30(config, m_duart[2], 10_MHz_XTAL); // Z8513010VSC ESCC
|
||||
m_duart[2]->out_int_callback().set(duart_int, FUNC(input_merger_device::in_w<2>));
|
||||
|
||||
// serial port 3
|
||||
// FIXME: HSKO/HSKI/GPI
|
||||
RS232_PORT(config, m_serial[2], default_rs232_devices, nullptr);
|
||||
m_duart[2]->out_txda_callback().set(m_serial[2], FUNC(rs232_port_device::write_txd));
|
||||
m_serial[2]->rxd_handler().set(m_duart[2], FUNC(z80scc_device::rxa_w));
|
||||
|
||||
// serial port 4
|
||||
// FIXME: HSKO/HSKI/GPI
|
||||
RS232_PORT(config, m_serial[3], default_rs232_devices, nullptr);
|
||||
m_duart[2]->out_txdb_callback().set(m_serial[3], FUNC(rs232_port_device::write_txd));
|
||||
m_serial[3]->rxd_handler().set(m_duart[2], FUNC(z80scc_device::rxb_w));
|
||||
|
||||
DSP56001(config, m_dsp, 20_MHz_XTAL);
|
||||
}
|
||||
|
||||
void pi4d2x_state::initialize()
|
||||
void ip6_state::initialize()
|
||||
{
|
||||
// map the configured ram
|
||||
m_cpu->space(0).install_ram(0x00000000, m_ram->mask(), m_ram->pointer());
|
||||
@ -916,13 +630,7 @@ void pi4d2x_state::initialize()
|
||||
m_leds.resolve();
|
||||
}
|
||||
|
||||
void pi4d3x_state::initialize()
|
||||
{
|
||||
// map the configured ram
|
||||
m_cpu->space(0).install_ram(0x00000000, m_ram->mask(), m_ram->pointer());
|
||||
}
|
||||
|
||||
void pi4d2x_state::lio_interrupt(unsigned number, int state)
|
||||
void ip6_state::lio_interrupt(unsigned number, int state)
|
||||
{
|
||||
u16 const mask = 1 << number;
|
||||
|
||||
@ -950,27 +658,7 @@ void pi4d2x_state::lio_interrupt(unsigned number, int state)
|
||||
}
|
||||
}
|
||||
|
||||
void pi4d3x_state::lio_interrupt(unsigned const lio, unsigned const number, int state)
|
||||
{
|
||||
u8 const mask = 1 << number;
|
||||
|
||||
// record interrupt state
|
||||
if (state)
|
||||
m_lio_isr[lio] |= mask;
|
||||
else
|
||||
m_lio_isr[lio] &= ~mask;
|
||||
|
||||
// update interrupt line
|
||||
bool const lio_int = m_lio_isr[lio] & m_lio_imr[lio];
|
||||
if (m_lio_int[lio] ^ lio_int)
|
||||
{
|
||||
m_lio_int[lio] = lio_int;
|
||||
|
||||
m_cpu->set_input_line(lio ? INPUT_LINE_IRQ2 : INPUT_LINE_IRQ1, lio_int);
|
||||
}
|
||||
}
|
||||
|
||||
void pi4d2x_state::scsi_drq(int state)
|
||||
void ip6_state::scsi_drq(int state)
|
||||
{
|
||||
if (state)
|
||||
{
|
||||
@ -984,7 +672,7 @@ void pi4d2x_state::scsi_drq(int state)
|
||||
}
|
||||
}
|
||||
|
||||
u8 pi4d2x_state::sysid_r()
|
||||
u8 ip6_state::sysid_r()
|
||||
{
|
||||
u8 data = m_sysid;
|
||||
|
||||
@ -994,7 +682,7 @@ u8 pi4d2x_state::sysid_r()
|
||||
return data;
|
||||
}
|
||||
|
||||
ROM_START(4d20)
|
||||
ROM_START(pi4d20)
|
||||
ROM_REGION32_BE(0x40000, "boot", 0)
|
||||
// 3.2e firmware has been found in both 4D/20 and 4D/25 hardware
|
||||
ROM_SYSTEM_BIOS(0, "3.2e", "Version 3.2 Rev E, Fri Jul 14 14:37:38 PDT 1989 SGI")
|
||||
@ -1016,7 +704,7 @@ ROM_START(4d20)
|
||||
ROMX_LOAD("070_8000_003_boot_3.h1e6", 0x000003, 0x010000, CRC(48b9322c) SHA1(600554a0ccc4bab4881a96a9886eea40cd04c8e4), ROM_BIOS(2) | ROM_SKIP(3))
|
||||
ROM_END
|
||||
|
||||
ROM_START(4d25)
|
||||
ROM_START(pi4d25)
|
||||
ROM_REGION32_BE(0x40000, "boot", 0)
|
||||
ROM_SYSTEM_BIOS(0, "3.2e", "Version 3.2 Rev E, Fri Jul 14 14:37:38 PDT 1989 SGI")
|
||||
ROMX_LOAD("070_8000_007_boot_0.h1c5", 0x000000, 0x010000, CRC(e448b865) SHA1(f0276b76360ea0b3250dbdaa7a1e57ea8f6144d6), ROM_BIOS(0) | ROM_SKIP(3))
|
||||
@ -1025,30 +713,8 @@ ROM_START(4d25)
|
||||
ROMX_LOAD("070_8000_007_boot_3.h1e6", 0x000003, 0x010000, CRC(682977c3) SHA1(d9bcf7cdc5caef4221929fe26eccf34253fa7f29), ROM_BIOS(0) | ROM_SKIP(3))
|
||||
ROM_END
|
||||
|
||||
ROM_START(4d30)
|
||||
ROM_REGION16_BE(0x80000, "boot", 0)
|
||||
ROM_SYSTEM_BIOS(0, "4.0.1c", "SGI Version 4.0.1 Rev C GR1/GR2/LG1, Feb 14, 1992")
|
||||
ROMX_LOAD("ip14prom.bin", 0x000000, 0x080000, NO_DUMP, ROM_BIOS(0))
|
||||
ROM_END
|
||||
|
||||
ROM_START(4d35)
|
||||
ROM_REGION16_BE(0x80000, "boot", 0) // TC574096D-120 (262,144x16-bit EEPROM)
|
||||
|
||||
ROM_SYSTEM_BIOS(0, "4.0.1d", "SGI Version 4.0.1 Rev D LG1/GR2, Mar 24, 1992")
|
||||
ROMX_LOAD("ip12prom.002be.u61", 0x000000, 0x040000, CRC(d35f105c) SHA1(3d08dfb961d7512bd8ed41cb6e01e89d14134f09), ROM_BIOS(0))
|
||||
|
||||
ROM_SYSTEM_BIOS(1, "4.0.1c", "SGI Version 4.0.1 Rev C GR1/GR2/LG1, Feb 14, 1992")
|
||||
ROMX_LOAD("ip12prom.070-8086-002.u61", 0x000000, 0x080000, CRC(543cfc3f) SHA1(a7331876f11bff40c960f822923503eca17191c5), ROM_BIOS(1))
|
||||
|
||||
ROM_SYSTEM_BIOS(2, "4.0a", "SGI Version 4.0 Rev A IP12, Aug 22, 1991")
|
||||
ROMX_LOAD("ip12prom.070-8045-002.u61", 0x000000, 0x040000, CRC(fe999bae) SHA1(eb054c365a6e018be3b9ae44169c0ffc6447c6f0), ROM_BIOS(2))
|
||||
ROM_END
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
|
||||
COMP(1988, 4d20, 0, 0, pi4d20, 0, pi4d2x_state, initialize, "Silicon Graphics Inc", "Personal IRIS 4D/20", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
|
||||
COMP(1989, 4d25, 0, 0, pi4d25, 0, pi4d2x_state, initialize, "Silicon Graphics Inc", "Personal IRIS 4D/25", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
|
||||
COMP(1991, 4d30, 0, 0, pi4d30, 0, pi4d3x_state, initialize, "Silicon Graphics Inc", "Personal IRIS 4D/30", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
|
||||
COMP(1991, 4d35, 0, 0, pi4d35, 0, pi4d3x_state, initialize, "Silicon Graphics Inc", "Personal IRIS 4D/35", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
|
||||
COMP(1988, pi4d20, 0, 0, pi4d20, 0, ip6_state, initialize, "Silicon Graphics", "Personal IRIS 4D/20", MACHINE_NO_SOUND | MACHINE_IMPERFECT_GRAPHICS)
|
||||
COMP(1989, pi4d25, 0, 0, pi4d25, 0, ip6_state, initialize, "Silicon Graphics", "Personal IRIS 4D/25", MACHINE_NO_SOUND | MACHINE_IMPERFECT_GRAPHICS)
|
237
src/mame/sgi/pic1.cpp
Normal file
237
src/mame/sgi/pic1.cpp
Normal file
@ -0,0 +1,237 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Patrick Mackinlay
|
||||
|
||||
/*
|
||||
* Silicon Graphics Processor Interface Controller (PIC1).
|
||||
*
|
||||
* TODO:
|
||||
* - parity
|
||||
* - graphics dma
|
||||
* - vme bus
|
||||
*
|
||||
*/
|
||||
#include "emu.h"
|
||||
#include "pic1.h"
|
||||
|
||||
//#define VERBOSE (LOG_GENERAL)
|
||||
|
||||
#include "logmacro.h"
|
||||
|
||||
DEFINE_DEVICE_TYPE(SGI_PIC1, sgi_pic1_device, "sgi_pic1", "SGI PIC1")
|
||||
|
||||
enum config_mask : u32
|
||||
{
|
||||
CONFIG_RFE = 0x0001, // refresh enable
|
||||
CONFIG_BIGEND = 0x0002, // endianness
|
||||
CONFIG_DBE = 0x0004, // enable data block refill
|
||||
CONFIG_IBE = 0x0008, // enable instr block refill
|
||||
CONFIG_GDE = 0x0010, // graphics dma complete int enable
|
||||
CONFIG_GSE = 0x0020, // graphics dma sync enable
|
||||
CONFIG_FREF = 0x0040, // fast refresh (giobus >= 33 mhz)
|
||||
CONFIG_DVMEBE = 0x0080, // disable vme bus error
|
||||
CONFIG_OLDFREF = 0x0080, // rfr for pre pic1.5 (rev <= b)
|
||||
CONFIG_GR2 = 0x0100, // gr2 giobus mode
|
||||
CONFIG_INIT = 0x0200, // drive vme sysreset (will reset cpu)
|
||||
CONFIG_ENPAR = 0x0400, // parity check on memory reads
|
||||
CONFIG_SLAVE = 0x0800, // allow slave accesses to board
|
||||
CONFIG_ARB = 0x1000, // enable vme arbiter function
|
||||
CONFIG_BADPAR = 0x2000, // write bad parity
|
||||
CONFIG_DOG = 0x4000, // enable watchdog timeout
|
||||
CONFIG_GRRESET = 0x8000, // reset graphics subsystem
|
||||
};
|
||||
|
||||
enum sid_mask : u32
|
||||
{
|
||||
SID_FPPRES = 0x0001, // fpu present (1=absent)
|
||||
SID_DMAERR = 0x0004, // dma error
|
||||
SID_DMAIDLE = 0x0008, // dma ended
|
||||
SID_VMERMW = 0x0020, // vme read-modify-write cycle active
|
||||
SID_REV = 0x01c0, // chip revision
|
||||
|
||||
SID_REVA = 0x0000,
|
||||
SID_REVB = 0x0040,
|
||||
SID_REVC = 0x0080,
|
||||
};
|
||||
|
||||
sgi_pic1_device::sgi_pic1_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
|
||||
: device_t(mconfig, SGI_PIC1, tag, owner, clock)
|
||||
, m_bus(*this, finder_base::DUMMY_TAG, -1, 32)
|
||||
, m_simms(*this, "SIMMS")
|
||||
, m_memcfg{ 0x003f003f, 0x003f003f }
|
||||
{
|
||||
}
|
||||
|
||||
void sgi_pic1_device::device_start()
|
||||
{
|
||||
}
|
||||
|
||||
void sgi_pic1_device::device_reset()
|
||||
{
|
||||
u8 const simms = m_simms->read();
|
||||
|
||||
// allocate installed memory
|
||||
unsigned bank16m = 0;
|
||||
for (unsigned bank = 0; bank < 4; bank++)
|
||||
{
|
||||
unsigned const size = BIT(simms, bank * 2, 2);
|
||||
|
||||
switch (size)
|
||||
{
|
||||
case 0:
|
||||
LOG("ram bank %c empty\n", bank + 'A');
|
||||
m_ram[bank].reset();
|
||||
break;
|
||||
case 2:
|
||||
bank16m++;
|
||||
[[fallthrough]];
|
||||
default:
|
||||
LOG("ram bank %c size %dM\n", bank + 'A', 1U << (size + 2));
|
||||
m_ram[bank] = std::make_unique<u8[]>(1U << (size + 22));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bank16m > 1)
|
||||
logerror("invalid memory configuration, at most one bank may contain 4M SIMMs\n");
|
||||
|
||||
m_cpuctrl = CONFIG_BIGEND;
|
||||
|
||||
// assume memory configuration is invalidated by reset
|
||||
memcfg_w(0, 0x003f003f);
|
||||
memcfg_w(1, 0x003f003f);
|
||||
|
||||
m_sid = SID_DMAIDLE;
|
||||
|
||||
m_dabr = 0;
|
||||
}
|
||||
|
||||
void sgi_pic1_device::map(address_map &map)
|
||||
{
|
||||
// system registers
|
||||
map(0x0'0000, 0x0'0003).rw(FUNC(sgi_pic1_device::cpuctrl_r), FUNC(sgi_pic1_device::cpuctrl_w));
|
||||
//map(0x0'0004, 0x0'0007); // RSTCONFIG system mode register
|
||||
map(0x0'0008, 0x0'000b).r(FUNC(sgi_pic1_device::sid_r));
|
||||
|
||||
// memory configuration registers
|
||||
map(0x1'0000, 0x1'0007).rw(FUNC(sgi_pic1_device::memcfg_r), FUNC(sgi_pic1_device::memcfg_w));
|
||||
//map(0x1'0100, 0x1'0103); // REFTIM0 refresh timer (wo)
|
||||
|
||||
// memory parity error registers
|
||||
map(0x1'0200, 0x1'0203).nopr(); // PARERR parity error register (ro)
|
||||
map(0x1'0204, 0x1'0207).nopr(); // CPUPARADR cpu parity error address (ro)
|
||||
map(0x1'0208, 0x1'020b).nopr(); // DMAPARADR dma slave parity error address (ro)
|
||||
map(0x1'0210, 0x1'0213).w(FUNC(sgi_pic1_device::parcl_ws));
|
||||
|
||||
// gio bus config
|
||||
map(0x2'0000, 0x2'0003).nopw(); // GIO_SLOT0 slot 0 config register
|
||||
map(0x2'0004, 0x2'0007).nopw(); // GIO_SLOT1 slot 1 config register
|
||||
map(0x2'0008, 0x2'000b).nopw(); // GIO_BURST arbiter burst register
|
||||
map(0x2'000c, 0x2'000f).nopw(); // GIO_DELAY arbiter delay register
|
||||
|
||||
// three-way transfer
|
||||
//map(0x7'0000, 0x7'0003); // TW_TRIG 3-way transfer trigger data
|
||||
//map(0x8'0000, 0x8'0003); // TW_STATUS 3-way status (ro)
|
||||
//map(0x8'0004, 0x8'0007); // TW_START 3-way transfer start address (ro)
|
||||
//map(0x8'0008, 0x8'000b); // TW_MASK 3-way transfer address mask
|
||||
//map(0x8'000c, 0x8'000f); // TW_SUBS 3-way transfer address substitute
|
||||
|
||||
// graphics channel registers
|
||||
map(0xa'0000, 0xa'0003).rw(FUNC(sgi_pic1_device::dabr_r), FUNC(sgi_pic1_device::dabr_w));
|
||||
//map(0xa'0004, 0xa'0007); // buffer address (ro)
|
||||
//map(0xa'0008, 0xa'000b); // buffer length (ro)
|
||||
//map(0xa'000c, 0xa'000f); // graphics operand address (ro)
|
||||
//map(0xa'0010, 0xa'0013); // stride/line count (ro)
|
||||
//map(0xa'0014, 0xa'0017); // next descriptor pointer (ro)
|
||||
//map(0xa'0100, 0xa'0103); // start graphics dma
|
||||
}
|
||||
|
||||
void sgi_pic1_device::memcfg_w(offs_t offset, u32 data)
|
||||
{
|
||||
LOG("memcfg%d 0x%08x\n", offset, data);
|
||||
|
||||
// remove existing mapping
|
||||
for (unsigned bank = 0; bank < 2; bank++)
|
||||
{
|
||||
u32 const base = BIT(m_memcfg[offset], 16 - bank * 16, 6) << 22;
|
||||
|
||||
if (base != 0x3f)
|
||||
{
|
||||
unsigned const size = ram_size(offset * 2 + bank);
|
||||
if (size)
|
||||
{
|
||||
LOG("unmap bank %c 0x%08x to 0x%08x\n", offset * 2 + bank + 'A', base, base + size - 1);
|
||||
m_bus->unmap_readwrite(base, base + size - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_memcfg[offset] = data;
|
||||
|
||||
// install configured mapping
|
||||
for (unsigned bank = 0; bank < 2; bank++)
|
||||
{
|
||||
u32 const base = BIT(m_memcfg[offset], 16 - bank * 16, 6) << 22;
|
||||
|
||||
if (base != 0x3f)
|
||||
{
|
||||
unsigned const size = ram_size(offset * 2 + bank);
|
||||
if (size)
|
||||
{
|
||||
LOG("remap bank %c 0x%08x to 0x%08x\n", offset * 2 + bank + 'A', base, base + size - 1);
|
||||
m_bus->install_ram(base, base + size - 1, m_ram[offset * 2 + bank].get());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sgi_pic1_device::parcl_ws(u32 data)
|
||||
{
|
||||
LOG("clear parity error\n");
|
||||
}
|
||||
|
||||
// return bytes available in a bank (minimum of installed and configured ram)
|
||||
unsigned sgi_pic1_device::ram_size(unsigned bank) const
|
||||
{
|
||||
unsigned const inst_size = BIT(m_simms->read(), bank * 2, 2);
|
||||
unsigned const conf_size = BIT(m_memcfg[bank >> 1], 24 - (bank & 1) * 16, 4);
|
||||
|
||||
if (inst_size && conf_size)
|
||||
return std::min((conf_size + 1) << 22, 1U << (inst_size + 22));
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INPUT_PORTS_START(pic1)
|
||||
PORT_START("VALID")
|
||||
PORT_CONFNAME(0x0f, 0x00, "Valid Banks")
|
||||
|
||||
PORT_START("SIMMS")
|
||||
PORT_CONFNAME(0x03, 0x02, "RAM bank A") PORT_CONDITION("VALID", 0x01, EQUALS, 0x01)
|
||||
PORT_CONFSETTING(0x00, "Empty")
|
||||
PORT_CONFSETTING(0x01, "4x2M")
|
||||
PORT_CONFSETTING(0x02, "4x4M")
|
||||
PORT_CONFSETTING(0x03, "4x8M")
|
||||
|
||||
PORT_CONFNAME(0x0c, 0x00, "RAM bank B") PORT_CONDITION("VALID", 0x02, EQUALS, 0x02)
|
||||
PORT_CONFSETTING(0x00, "Empty")
|
||||
PORT_CONFSETTING(0x04, "4x2M")
|
||||
PORT_CONFSETTING(0x08, "4x4M")
|
||||
PORT_CONFSETTING(0x0c, "4x8M")
|
||||
|
||||
PORT_CONFNAME(0x30, 0x00, "RAM bank C") PORT_CONDITION("VALID", 0x04, EQUALS, 0x04)
|
||||
PORT_CONFSETTING(0x00, "Empty")
|
||||
PORT_CONFSETTING(0x10, "4x2M")
|
||||
PORT_CONFSETTING(0x20, "4x4M")
|
||||
PORT_CONFSETTING(0x30, "4x8M")
|
||||
|
||||
PORT_CONFNAME(0xc0, 0x00, "RAM bank D") PORT_CONDITION("VALID", 0x08, EQUALS, 0x08)
|
||||
PORT_CONFSETTING(0x00, "Empty")
|
||||
PORT_CONFSETTING(0x40, "4x2M")
|
||||
PORT_CONFSETTING(0x80, "4x4M")
|
||||
PORT_CONFSETTING(0xc0, "4x8M")
|
||||
INPUT_PORTS_END
|
||||
|
||||
ioport_constructor sgi_pic1_device::device_input_ports() const
|
||||
{
|
||||
return INPUT_PORTS_NAME(pic1);
|
||||
}
|
54
src/mame/sgi/pic1.h
Normal file
54
src/mame/sgi/pic1.h
Normal file
@ -0,0 +1,54 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Patrick Mackinlay
|
||||
|
||||
#ifndef MAME_SGI_PIC1_H
|
||||
#define MAME_SGI_PIC1_H
|
||||
|
||||
#pragma once
|
||||
|
||||
class sgi_pic1_device
|
||||
: public device_t
|
||||
{
|
||||
public:
|
||||
sgi_pic1_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
template <typename T> void set_bus(T &&tag, int spacenum) { m_bus.set_tag(std::forward<T>(tag), spacenum); }
|
||||
|
||||
void map(address_map &map);
|
||||
|
||||
protected:
|
||||
// device_t implementation
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
virtual ioport_constructor device_input_ports() const override;
|
||||
|
||||
// read handlers
|
||||
u32 cpuctrl_r() { return m_cpuctrl; }
|
||||
u32 sid_r() { return m_sid; }
|
||||
u32 memcfg_r(offs_t offset) { return m_memcfg[offset]; }
|
||||
u32 dabr_r() { return m_dabr; }
|
||||
|
||||
// write handlers
|
||||
void cpuctrl_w(u32 data) { m_cpuctrl = data; }
|
||||
void memcfg_w(offs_t offset, u32 data);
|
||||
void parcl_ws(u32 data);
|
||||
void dabr_w(u32 data) { m_dabr = data; }
|
||||
|
||||
// helpers
|
||||
unsigned ram_size(unsigned bank) const;
|
||||
|
||||
private:
|
||||
required_address_space m_bus;
|
||||
required_ioport m_simms;
|
||||
|
||||
std::unique_ptr<u8[]> m_ram[4];
|
||||
|
||||
u32 m_cpuctrl; // cpu board control and status
|
||||
u32 m_sid; // system id/coprocessor present
|
||||
u32 m_memcfg[2]; // memory configuration
|
||||
u32 m_dabr; // descriptor array base
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(SGI_PIC1, sgi_pic1_device)
|
||||
|
||||
#endif // MAME_SGI_PIC1_H
|
Loading…
Reference in New Issue
Block a user