diff options
author | Patrick Mackinlay <pmackinlay@hotmail.com> | 2019-06-28 16:25:21 +0700 |
---|---|---|
committer | Patrick Mackinlay <pmackinlay@hotmail.com> | 2019-06-28 16:25:21 +0700 |
commit | b910a955e2e12199c2ffee2f90b895e30a1b9eb3 (patch) | |
tree | 6b06917acd51e16f1fe1df2a25e24faa3e0a4529 | |
parent | 2f776995c370e3f939ef49608e03945c390e5a28 (diff) |
4dpi: wip checkpoint (nw)
-rw-r--r-- | src/mame/drivers/4dpi.cpp | 460 | ||||
-rw-r--r-- | src/mame/mame.lst | 2 |
2 files changed, 237 insertions, 225 deletions
diff --git a/src/mame/drivers/4dpi.cpp b/src/mame/drivers/4dpi.cpp index 191edfbd51d..5416bdf9d50 100644 --- a/src/mame/drivers/4dpi.cpp +++ b/src/mame/drivers/4dpi.cpp @@ -20,260 +20,272 @@ 1991 4D/35 IP12 R3000 36MHz ****************************************************************************/ +/* + * Sources: + * - 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 + * - https://github.com/NetBSD/src/tree/trunk/sys/arch/sgimips/ + * + * TODO: + * - IOC1 and CTL1 + * - graphics, keyboard, mouse, audio + * + * Status: + * - hangs waiting for wd33c93 reset interrupt + * - if bypassed, hangs waiting on a timer(?) at bfa40004 + */ #include "emu.h" + +// cpu and memory #include "cpu/mips/mips1.h" +#include "machine/ram.h" +#include "machine/eepromser.h" + +// other devices +#include "machine/wd33c9x.h" +#include "machine/am79c90.h" +#include "machine/mc68681.h" +#include "machine/pit8253.h" +#include "machine/dp8573.h" + +// buses and connectors +#include "machine/nscsi_bus.h" +#include "machine/nscsi_hd.h" +#include "machine/nscsi_cd.h" +#include "bus/rs232/rs232.h" + +// video and audio #include "screen.h" +#define LOG_GENERAL (1U << 0) -struct ip6_regs_t -{ - uint16_t unknown_half_0; - uint8_t unknown_byte_0; - uint8_t unknown_byte_1; -}; +#define VERBOSE (LOG_GENERAL) +#include "logmacro.h" -class sgi_ip6_state : public driver_device +class ip6_state : public driver_device { public: - sgi_ip6_state(const machine_config &mconfig, device_type type, const char *tag) - : driver_device(mconfig, type, tag) , - m_maincpu(*this, "maincpu") { } - - void sgi_ip6(machine_config &config); - - void init_sgi_ip6(); - -private: - ip6_regs_t m_ip6_regs; - DECLARE_READ32_MEMBER(ip6_unk1_r); - DECLARE_WRITE32_MEMBER(ip6_unk1_w); - DECLARE_READ32_MEMBER(ip6_unk2_r); - DECLARE_WRITE32_MEMBER(ip6_unk2_w); - DECLARE_READ32_MEMBER(ip6_unk3_r); - DECLARE_WRITE32_MEMBER(ip6_unk3_w); - virtual void machine_start() override; - virtual void machine_reset() override; - virtual void video_start() override; - uint32_t screen_update_sgi_ip6(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); - INTERRUPT_GEN_MEMBER(sgi_ip6_vbl); - inline void ATTR_PRINTF(3,4) verboselog( int n_level, const char *s_fmt, ... ); - required_device<r2000_device> m_maincpu; - void sgi_ip6_map(address_map &map); -}; - - -#define VERBOSE_LEVEL (0) - -#define ENABLE_VERBOSE_LOG (1) - -inline void ATTR_PRINTF(3,4) sgi_ip6_state::verboselog( int n_level, const char *s_fmt, ... ) -{ -#if ENABLE_VERBOSE_LOG - if( VERBOSE_LEVEL >= n_level ) - { - va_list v; - char buf[ 32768 ]; - va_start( v, s_fmt ); - vsprintf( buf, s_fmt, v ); - va_end( v ); - logerror("%s: %s", machine().describe_context(), buf); - } -#endif -} - -/*************************************************************************** - VIDEO HARDWARE -***************************************************************************/ - -void sgi_ip6_state::video_start() -{ -} - -uint32_t sgi_ip6_state::screen_update_sgi_ip6(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) -{ - return 0; -} - -/*************************************************************************** - MACHINE FUNCTIONS -***************************************************************************/ - - -READ32_MEMBER(sgi_ip6_state::ip6_unk1_r) -{ - uint32_t ret = 0; - switch(offset) + 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") + , m_eeprom(*this, "eeprom") + , m_rtc(*this, "rtc") + , m_pit(*this, "pit") + , m_scsi(*this, "scsi:0:wd33c93") + , m_net(*this, "net") + , m_duart(*this, "duart%u", 0U) + , m_serial(*this, "serial%u", 0U) { - case 0x0000/4: - if(ACCESSING_BITS_16_31) - { - verboselog(0, "ip6_unk1_r: Unknown address: %08x & %08x\n", 0x1f880000 + (offset << 2), mem_mask ); - } - if(ACCESSING_BITS_0_15) - { - verboselog(0, "ip6_unk1_r: Unknown Halfword 0: %08x & %08x\n", m_ip6_regs.unknown_half_0, mem_mask ); - ret |= m_ip6_regs.unknown_half_0; - } - break; - default: - verboselog(0, "ip6_unk1_r: Unknown address: %08x & %08x\n", 0x1f880000 + (offset << 2), mem_mask ); - break; } - return ret; -} -WRITE32_MEMBER(sgi_ip6_state::ip6_unk1_w) -{ - switch(offset) - { - case 0x0000/4: - if(ACCESSING_BITS_16_31) - { - verboselog(0, "ip6_unk1_w: Unknown address: %08x = %08x & %08x\n", 0x1f880000 + (offset << 2), data, mem_mask ); - } - if(ACCESSING_BITS_0_15) - { - verboselog(0, "ip6_unk1_w: Unknown Halfword 0 = %04x & %04x\n", data & 0x0000ffff, mem_mask & 0x0000ffff ); - m_ip6_regs.unknown_half_0 = data & 0x0000ffff; - } - break; - default: - verboselog(0, "ip6_unk1_w: Unknown address: %08x = %08x & %08x\n", 0x1f880000 + (offset << 2), data, mem_mask ); - break; - } -} + void configure(machine_config &config); + void initialize(); -READ32_MEMBER(sgi_ip6_state::ip6_unk2_r) -{ - uint32_t ret = 0; - switch(offset) - { - case 0x0000/4: - if(!ACCESSING_BITS_24_31) - { - verboselog(0, "ip6_unk2_r: Unknown address: %08x & %08x\n", 0x1f880000 + (offset << 2), mem_mask ); - } - if(ACCESSING_BITS_24_31) - { - verboselog(0, "ip6_unk2_r: Unknown Byte 0 = %02x & %02x\n", m_ip6_regs.unknown_byte_0, mem_mask >> 24 ); - ret |= m_ip6_regs.unknown_byte_0 << 24; - } - break; - default: - verboselog(0, "ip6_unk2_r: Unknown address: %08x & %08x\n", 0x1f880000 + (offset << 2), mem_mask ); - break; - } - return ret; -} +private: + required_device<mips1_device_base> m_cpu; + required_device<ram_device> m_ram; + required_device<eeprom_serial_93c56_16bit_device> m_eeprom; -WRITE32_MEMBER(sgi_ip6_state::ip6_unk2_w) -{ - switch(offset) - { - case 0x0000/4: - if(!ACCESSING_BITS_24_31) - { - verboselog(0, "ip6_unk2_w: Unknown address: %08x = %08x & %08x\n", 0x1f880000 + (offset << 2), data, mem_mask ); - } - if(ACCESSING_BITS_24_31) - { - verboselog(0, "ip6_unk2_w: Unknown Byte 0 = %02x & %02x\n", data >> 24, mem_mask >> 24 ); - m_ip6_regs.unknown_byte_0 = (data & 0xff000000) >> 24; - } - break; - default: - verboselog(0, "ip6_unk2_w: Unknown address: %08x = %08x & %08x\n", 0x1f880000 + (offset << 2), data, mem_mask ); - break; - } -} + required_device<dp8573_device> m_rtc; + required_device<pit8254_device> m_pit; + required_device<wd33c93_device> m_scsi; + required_device<am7990_device> m_net; + required_device_array<scn2681_device, 2> m_duart; + required_device_array<rs232_port_device, 2> m_serial; -READ32_MEMBER(sgi_ip6_state::ip6_unk3_r) -{ - uint32_t ret = 0; - if(ACCESSING_BITS_16_23) - { - verboselog(0, "ip6_unk3_r: Unknown Byte 1: %02x & %02x\n", m_ip6_regs.unknown_byte_1, (mem_mask >> 16) & 0x000000ff); - ret |= m_ip6_regs.unknown_byte_1 << 16; - } - else - { - verboselog(0, "ip6_unk3_r: Unknown address: %08x & %08x\n", 0x1fb00000 + (offset << 2), mem_mask ); - } - return ret; -} + void map(address_map &map); -WRITE32_MEMBER(sgi_ip6_state::ip6_unk3_w) -{ - verboselog(0, "ip6_unk3_w: Unknown address: %08x = %08x & %08x\n", 0x1fb00000 + (offset << 2), data, mem_mask ); -} + u8 m_ctl_sysid; + u8 m_aux_cpuctrl; + u16 m_ctl_cpuctrl; -INTERRUPT_GEN_MEMBER(sgi_ip6_state::sgi_ip6_vbl) -{ -} + u8 m_int_mask; +}; -void sgi_ip6_state::machine_start() +void ip6_state::map(address_map &map) { + //map(0x10000000, 0x1bffffff); // a32 kernel vme bus, vme modifier 0x09 + //map(0x1c000000, 0x1cffffff); // a24 kernel vme bus, vme modifier 0x3d + //map(0x1e000000, 0x1effffff); // a24 kernel vme bus, vme modifier 0x39 + + //map(0x1f900000, 0x1f900000); // i/o controller (also lance and scsi) + + map(0x1f800000, 0x1f800003).lr8("ctl_sysid", [this]() { return m_ctl_sysid; }).umask32(0x00ff0000); + + map(0x1f840008, 0x1f84000b).ram().umask32(0x000000ff); // vme mask? + + map(0x1f880000, 0x1f880003).lrw16("ctl_cpuctrl", + [this]() + { + return m_ctl_cpuctrl; + }, + [this](u16 data) + { + m_eeprom->di_write(BIT(data, 8)); + + //BIT(data, 9); // reset system + //BIT(data, 10); // enable parity checking + //BIT(data, 11); // enable slave accesses + //BIT(data, 14); // watchdog enable + + m_ctl_cpuctrl = data; + }).umask32(0x0000ffff); + map(0x1f8e0000, 0x1f8e0003).lrw8("aux_cpuctrl", + [this]() + { + return m_aux_cpuctrl; + }, + [this](u8 data) + { + //BIT(data, 1); // heartbeat + //BIT(data, 4); // enable console led(?)/eeprom program enable? + m_eeprom->cs_write(BIT(data, 5)); + m_eeprom->clk_write(BIT(data, 6)); + + m_aux_cpuctrl = data; + }).umask32(0xff000000); + + map(0x1f950000, 0x1f9501ff).rw(m_net, FUNC(am7990_device::regs_r), FUNC(am7990_device::regs_w)).umask32(0xffff0000); + + // local interrupt goes to cpu interrupt 1 + //map(0x1f980000, 0x1f980003).r().umask32(0x0000ffff); // int1_local_status + map(0x1f980008, 0x1f98000b).lrw8("int_mask", [this]() { return m_int_mask; }, [this](u8 data) { m_int_mask = data; }).umask32(0x000000ff); // int1_local_mask + + map(0x1fa00000, 0x1fa00003).lr8("timer1_ack", [this]() { m_cpu->set_input_line(INPUT_LINE_IRQ4, 0); return 0; }).umask32(0xff000000); + map(0x1fa20000, 0x1fa20003).lr8("timer0_ack", [this]() { m_cpu->set_input_line(INPUT_LINE_IRQ2, 0); return 0; }).umask32(0xff000000); + //map(0x1fa40000, 0x1fa4000f).rw(m_pit, FUNC(pit8254_device::read), FUNC(pit8254_device::write)).umask32(0xff000000); // NetBSD says 0x1fb40000? + + map(0x1fa80000, 0x1fa80007).lr32("scsi_reset", [this](offs_t offset) { m_scsi->reset_w(!!offset); return 0; }); + + // TODO: firmware resets wd33c93 and expects it to produce an interrupt - device emulation is currently wrong + map(0x1fb00000, 0x1fb00003).rw(m_scsi, FUNC(wd33c93_device::indir_addr_r), FUNC(wd33c93_device::indir_addr_w)).umask32(0x00ff0000); + map(0x1fb00100, 0x1fb00103).rw(m_scsi, FUNC(wd33c93_device::indir_reg_r), FUNC(wd33c93_device::indir_reg_w)).umask32(0x00ff0000); + + map(0x1fb40000, 0x1fb4000f).rw(m_pit, FUNC(pit8254_device::read), FUNC(pit8254_device::write)).umask32(0xff000000); + + map(0x1fb80000, 0x1fb800ff).lrw8("duart0", + [this](offs_t offset) + { + return m_duart[0]->read(offset >> 2); + }, + [this](offs_t offset, u8 data) + { + m_duart[0]->write(offset >> 2, data); + }).umask32(0xff000000); + + map(0x1fbc0000, 0x1fbc00ff).rw(m_rtc, FUNC(dp8573_device::read), FUNC(dp8573_device::write)).umask32(0xff000000); + + map(0x1fc00000, 0x1fc3ffff).rom().region("prom", 0); } -void sgi_ip6_state::machine_reset() +static void scsi_devices(device_slot_interface &device) { - m_ip6_regs.unknown_byte_0 = 0x80; - m_ip6_regs.unknown_byte_1 = 0x80; - m_ip6_regs.unknown_half_0 = 0; + device.option_add("cdrom", NSCSI_CDROM); + device.option_add("harddisk", NSCSI_HARDDISK); } -/*************************************************************************** - ADDRESS MAPS -***************************************************************************/ - -void sgi_ip6_state::sgi_ip6_map(address_map &map) +void ip6_state::configure(machine_config &config) { - map(0x1f880000, 0x1f880003).rw(FUNC(sgi_ip6_state::ip6_unk1_r), FUNC(sgi_ip6_state::ip6_unk1_w)); - map(0x1fb00000, 0x1fb00003).rw(FUNC(sgi_ip6_state::ip6_unk3_r), FUNC(sgi_ip6_state::ip6_unk3_w)); - map(0x1fbc004c, 0x1fbc004f).rw(FUNC(sgi_ip6_state::ip6_unk2_r), FUNC(sgi_ip6_state::ip6_unk2_w)); - map(0x1fc00000, 0x1fc3ffff).rom().region("user1", 0); + R2000A(config, m_cpu, 25_MHz_XTAL / 2, 16384, 8192); + m_cpu->set_endianness(ENDIANNESS_BIG); + m_cpu->set_addrmap(AS_PROGRAM, &ip6_state::map); + m_cpu->set_fpu(mips1_device_base::MIPS_R2010A); + m_cpu->in_brcond<0>().set([]() { return 1; }); // writeback complete + + // 16 SIMM slots with 1, 2 or 4MB SIMMs installed in sets of 4 + RAM(config, m_ram); + m_ram->set_default_size("16M"); + m_ram->set_extra_options("4M,8M,12M,32M,48M,64M"); + m_ram->set_default_value(0); + + EEPROM_93C56_16BIT(config, m_eeprom); + m_eeprom->do_callback().set( + [this](int state) + { + if (state) + m_ctl_sysid |= 0x01; + else + m_ctl_sysid &= ~0x01; + }); + + DP8573(config, m_rtc); + + PIT8254(config, m_pit); + m_pit->set_clk<2>(3.6864_MHz_XTAL); + m_pit->out_handler<0>().set_inputline(m_cpu, INPUT_LINE_IRQ2); + m_pit->out_handler<1>().set_inputline(m_cpu, INPUT_LINE_IRQ4); + 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("wd33c93", WD33C93).machine_config( + [](device_t *device) + { + device->set_clock(10000000); + + // TODO: connect irq and 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, "cdrom", false); + NSCSI_CONNECTOR(config, "scsi:7", scsi_devices, nullptr, false); + + AM7990(config, m_net); + // TODO: irq, drq, memory accessors (via ioc) + + // duarts + // NOTE: one of these is has 40 pins, while the other has only 24 pins; most + // likely the keyboard/mouse one is without and doesn't have any flow control + SCN2681(config, m_duart[0], 3.6864_MHz_XTAL); + SCN2681(config, m_duart[1], 3.6864_MHz_XTAL); // TODO: probably for the keyboard and mouse + RS232_PORT(config, m_serial[0], default_rs232_devices, "terminal"); + RS232_PORT(config, m_serial[1], default_rs232_devices, nullptr); + + // duart 0 outputs + // TODO: irq + m_duart[0]->a_tx_cb().set(m_serial[0], FUNC(rs232_port_device::write_txd)); + m_duart[0]->b_tx_cb().set(m_serial[1], FUNC(rs232_port_device::write_txd)); + m_duart[0]->outport_cb().set( + [this](u8 data) + { + m_serial[0]->write_rts(BIT(data, 0)); + m_serial[1]->write_rts(BIT(data, 1)); + m_serial[0]->write_dtr(BIT(data, 2)); + m_serial[1]->write_dtr(BIT(data, 3)); + + // TODO: bit 4-7 + }); + + // duart inputs (guessed for now) + m_serial[0]->rxd_handler().set(m_duart[0], FUNC(scn2681_device::rx_a_w)); + m_serial[0]->cts_handler().set(m_duart[0], FUNC(scn2681_device::ip0_w)); + m_serial[0]->dsr_handler().set(m_duart[0], FUNC(scn2681_device::ip3_w)); + m_serial[0]->dcd_handler().set(m_duart[0], FUNC(scn2681_device::ip4_w)); + + m_serial[1]->rxd_handler().set(m_duart[0], FUNC(scn2681_device::rx_b_w)); + m_serial[1]->cts_handler().set(m_duart[0], FUNC(scn2681_device::ip1_w)); + m_serial[1]->dsr_handler().set(m_duart[0], FUNC(scn2681_device::ip5_w)); + m_serial[1]->dcd_handler().set(m_duart[0], FUNC(scn2681_device::ip6_w)); } -/*************************************************************************** - MACHINE DRIVERS -***************************************************************************/ - -void sgi_ip6_state::sgi_ip6(machine_config &config) +void ip6_state::initialize() { - R2000(config, m_maincpu, 25_MHz_XTAL / 2, 16384, 8192); - m_maincpu->set_endianness(ENDIANNESS_BIG); - m_maincpu->set_addrmap(AS_PROGRAM, &sgi_ip6_state::sgi_ip6_map); - m_maincpu->set_vblank_int("screen", FUNC(sgi_ip6_state::sgi_ip6_vbl)); - - /* video hardware */ - screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); - screen.set_refresh_hz(60); - screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500)); /* not accurate */ - screen.set_size(640, 480); - screen.set_visarea(0, 640-1, 0, 480-1); - screen.set_screen_update(FUNC(sgi_ip6_state::screen_update_sgi_ip6)); -} + // map the configured ram + m_cpu->space(0).install_ram(0x00000000, m_ram->mask(), m_ram->pointer()); -static INPUT_PORTS_START( sgi_ip6 ) - PORT_START("UNUSED") // unused IN0 - PORT_BIT(0xffff, IP_ACTIVE_HIGH, IPT_UNUSED) -INPUT_PORTS_END - -void sgi_ip6_state::init_sgi_ip6() -{ + m_ctl_sysid = 0x02; // fpu present } -/*************************************************************************** - - ROM definition(s) - -***************************************************************************/ - -ROM_START( sgi_ip6 ) - ROM_REGION32_BE( 0x40000, "user1", 0 ) - ROM_LOAD( "4d202031.bin", 0x000000, 0x040000, CRC(065a290a) SHA1(6f5738e79643f94901e6efe3612468d14177f65b) ) +ROM_START(4d20) + ROM_REGION32_BE(0x40000, "prom", 0) + ROM_LOAD("4d202031.bin", 0x000000, 0x040000, CRC(065a290a) SHA1(6f5738e79643f94901e6efe3612468d14177f65b)) ROM_END -// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS -COMP( 1988, sgi_ip6, 0, 0, sgi_ip6, sgi_ip6, sgi_ip6_state, init_sgi_ip6, "Silicon Graphics Inc", "4D/20", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) +// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS +COMP(1988, 4d20, 0, 0, configure, 0, ip6_state, initialize, "Silicon Graphics Inc", "4D/20", MACHINE_NOT_WORKING | MACHINE_NO_SOUND) diff --git a/src/mame/mame.lst b/src/mame/mame.lst index cd3cc8f2da1..072ecbdcf42 100644 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -93,7 +93,7 @@ undoukai // A17 (c) 1984 Taito 4d410 // (c) SGI 1991 @source:4dpi.cpp -sgi_ip6 // IP6: 4D/PI, R2000, 20MHz +4d20 // IP6: Personal Iris 4D/20, R2000 @12.5MHz @source:4enlinea.cpp 4enlinea // (c) 1991 System Compumatic |