diff --git a/src/devices/cpu/mips/mips1.h b/src/devices/cpu/mips/mips1.h index 3319fcdefe2..a64521b1bf6 100644 --- a/src/devices/cpu/mips/mips1.h +++ b/src/devices/cpu/mips/mips1.h @@ -9,6 +9,18 @@ class mips1core_device_base : public cpu_device { public: + // floating point coprocessor revision numbers recognised by RISC/os 4.52 and IRIX + enum fpu_rev_t : u32 + { + MIPS_R2360 = 0x0100, // MIPS R2360 Floating Point Board + MIPS_R2010 = 0x0200, // MIPS R2010 VLSI Floating Point Chip + MIPS_R2010A = 0x0310, // MIPS R2010A VLSI Floating Point Chip + MIPS_R3010 = 0x0320, // MIPS R3010 VLSI Floating Point Chip + MIPS_R3010A = 0x0330, // MIPS R3010A VLSI Floating Point Chip + MIPS_R3010Av4 = 0x0340, // MIPS R3010A VLSI Floating Point Chip + MIPS_R6010 = 0x0400, // MIPS R6010 Floating Point Chip + }; + // device configuration void set_endianness(endianness_t endianness) { m_endianness = endianness; } void set_fpurev(u32 revision) { m_hasfpu = true; m_fpurev = revision; } diff --git a/src/mame/drivers/mips.cpp b/src/mame/drivers/mips.cpp index 27afe08ecad..f1b3f833181 100644 --- a/src/mame/drivers/mips.cpp +++ b/src/mame/drivers/mips.cpp @@ -39,6 +39,8 @@ * http://www.umips.net/ * http://www.geekdot.com/the-mips-rs2030/ * http://www.jp.netbsd.org/ports/mipsco/models.html + * http://www.prumpleffer.de/~miod/machineroom/machines/mips/magnum/index.html + * https://web.archive.org/web/20140518203135/http://no-l.org/pages/riscos.html * * TODO (rx2030) * - remaining iop interface @@ -178,6 +180,9 @@ * 3 <- fpu * 4 <- fdc * 5 <- parity error + * + * Keyboard controller output port + * 4: select 1M/4M SIMMs? */ #include "emu.h" @@ -472,8 +477,8 @@ static void mips_scsi_devices(device_slot_interface &device) void rx2030_state::rx2030(machine_config &config) { R2000A(config, m_cpu, 33.333_MHz_XTAL / 2, 32768, 32768); - m_cpu->set_fpurev(0x0315); // 0x0315 == R2010A v1.5 - m_cpu->in_brcond<0>().set([]() { return 1; }); // logerror("brcond0 sampled (%s)\n", machine().describe_context()); + m_cpu->set_fpurev(mips1_device_base::MIPS_R2010A); + m_cpu->in_brcond<0>().set([]() { return 1; }); // writeback complete V50(config, m_iop, 20_MHz_XTAL / 2); m_iop->set_addrmap(AS_PROGRAM, &rx2030_state::iop_program_map); @@ -728,14 +733,31 @@ void rx3230_state::rx3230_init() { // map the configured ram m_cpu->space(0).install_ram(0x00000000, m_ram->mask(), m_ram->pointer()); + + /* + * HACK: the prom bootp code broadcasts to the network address (i.e. the + * host portion is "all zeroes"), instead of to the standard "all ones". + * This makes it very difficult to receive the bootp request in a host OS, + * so this patch changes the code to broadcast to the standard broadcast + * address instead. + * + * 0xbfc1f1b0: addu r6,0,0 + * jal $bfc0be10 # set host portion from r6 + * + * This patch changes the first instruction to one which loads r6 with + * 0xffffffff, which is then or'd into the host part of the address, i.e.: + * + * addiu r6,0,-$1 + */ + m_rom[0x1f1b0 >> 2] = 0x2406ffff; } void rx3230_state::rx3230(machine_config &config) { R3000A(config, m_cpu, 50_MHz_XTAL / 2, 32768, 32768); m_cpu->set_addrmap(AS_PROGRAM, &rx3230_state::rx3230_map); - m_cpu->set_fpurev(0x0340); // 0x0340 == R3010A v4.0? - m_cpu->in_brcond<0>().set([]() { return 1; }); // bus grant? + m_cpu->set_fpurev(mips1_device_base::MIPS_R3010A); + m_cpu->in_brcond<0>().set([]() { return 1; }); // writeback complete // 32 SIMM slots, 8-128MB memory, banks of 8 1MB or 4MB SIMMs RAM(config, m_ram); @@ -748,6 +770,8 @@ void rx3230_state::rx3230(machine_config &config) m_rambo->parity_out().set_inputline(m_cpu, INPUT_LINE_IRQ5); //m_rambo->buzzer_out().set(m_buzzer, FUNC(speaker_sound_device::level_w)); m_rambo->set_ram(m_ram); + m_rambo->dma_r<0>().set("scsi:7:ncr53c94", FUNC(ncr53c94_device::dma_r)); + m_rambo->dma_w<0>().set("scsi:7:ncr53c94", FUNC(ncr53c94_device::dma_w)); // scsi bus and devices NSCSI_BUS(config, m_scsibus, 0); @@ -823,15 +847,15 @@ void rx3230_state::rx3230(machine_config &config) AT_KEYBOARD_CONTROLLER(config, m_kbdc, 12_MHz_XTAL); // TODO: confirm m_kbdc->kbd_clk().set(kbdc, FUNC(pc_kbdc_device::clock_write_from_mb)); m_kbdc->kbd_data().set(kbdc, FUNC(pc_kbdc_device::data_write_from_mb)); - m_kbdc->kbd_irq().set(FUNC(rx3230_state::irq_w)).invert(); + m_kbdc->kbd_irq().set(FUNC(rx3230_state::irq_w)); // buzzer SPEAKER(config, "mono").front_center(); SPEAKER_SOUND(config, m_buzzer); m_buzzer->add_route(ALL_OUTPUTS, "mono", 0.50); - // motherboard monochrome video (1152x900 @ 60Hz?) - u32 const pixclock = 62'208'000; + // motherboard monochrome video (1152x900 @ 72Hz) + u32 const pixclock = 74'649'600; SCREEN(config, m_screen, SCREEN_TYPE_RASTER); m_screen->set_raw(pixclock, 1152, 0, 1152, 900, 0, 900); diff --git a/src/mame/includes/mips.h b/src/mame/includes/mips.h index 0557387fa93..9a042988c36 100644 --- a/src/mame/includes/mips.h +++ b/src/mame/includes/mips.h @@ -144,6 +144,7 @@ public: : driver_device(mconfig, type, tag) , m_cpu(*this, "cpu") , m_ram(*this, "ram") + , m_rom(*this, "rx3230") , m_rambo(*this, "rambo") , m_scsibus(*this, "scsi") , m_scsi(*this, "scsi:7:ncr53c94") @@ -188,6 +189,7 @@ private: // processors and memory required_device m_cpu; required_device m_ram; + required_region_ptr m_rom; // i/o devices required_device m_rambo; diff --git a/src/mame/machine/mips_rambo.cpp b/src/mame/machine/mips_rambo.cpp index 86409db8642..2d6bd16e17c 100644 --- a/src/mame/machine/mips_rambo.cpp +++ b/src/mame/machine/mips_rambo.cpp @@ -10,8 +10,6 @@ * * TODO * - interrupts - * - dma - * - timer * - buzzer */ @@ -33,6 +31,7 @@ mips_rambo_device::mips_rambo_device(const machine_config &mconfig, const char * , m_parity_out_cb(*this) , m_timer_out_cb(*this) , m_buzzer_out_cb(*this) + , m_channel{{ 0,0,0,0,0,0, false, *this, *this }, { 0,0,0,0,0,0, false, *this, *this }} , m_irq_out_state(0) , m_buzzer_out_state(0) { @@ -68,6 +67,13 @@ void mips_rambo_device::device_start() m_timer_out_cb.resolve_safe(); m_buzzer_out_cb.resolve_safe(); + for (dma_t &ch : m_channel) + { + ch.read_cb.resolve_safe(0); + ch.write_cb.resolve_safe(); + } + + m_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(mips_rambo_device::timer), this)); m_buzzer_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(mips_rambo_device::buzzer_toggle), this)); } @@ -81,7 +87,11 @@ void mips_rambo_device::device_reset() READ32_MEMBER(mips_rambo_device::tcount_r) { - return attotime_to_clocks(machine().time() - m_tcount); + u32 const data = attotime_to_clocks(machine().time() - m_tcount); + + LOGMASKED(LOG_REG, "tcount_r 0x%08x (%s)\n", data, machine().describe_context()); + + return data; } WRITE32_MEMBER(mips_rambo_device::tcount_w) @@ -94,6 +104,10 @@ WRITE32_MEMBER(mips_rambo_device::tcount_w) WRITE32_MEMBER(mips_rambo_device::tbreak_w) { LOGMASKED(LOG_REG, "tbreak_w 0x%08x (%s)\n", data, machine().describe_context()); + + COMBINE_DATA(&m_tbreak); + + m_timer->adjust(clocks_to_attotime(m_tbreak) - (machine().time() - m_tcount)); } WRITE32_MEMBER(mips_rambo_device::control_w) @@ -130,6 +144,10 @@ template WRITE32_MEMBER(mips_rambo_device::mode_w) { LOGMASKED(LOG_REG, "mode_w<%d> 0x%08x (%s)\n", Channel, data, machine().describe_context()); + if (data & MODE_CHANNEL_EN) + m_channel[Channel].current_address = m_channel[Channel].load_address; + + mem_mask &= MODE_WRITE_MASK; COMBINE_DATA(&m_channel[Channel].mode); } @@ -138,6 +156,14 @@ template WRITE16_MEMBER(mips_rambo_device::block_count_w) LOGMASKED(LOG_REG, "block_count_w<%d> 0x%04x (%s)\n", Channel, data, machine().describe_context()); COMBINE_DATA(&m_channel[Channel].block_count); + COMBINE_DATA(&m_channel[Channel].reload_count); +} + +TIMER_CALLBACK_MEMBER(mips_rambo_device::timer) +{ + // FIXME: clear timer out line here, or on tcount/tbreak write? + m_timer_out_cb(ASSERT_LINE); + m_timer_out_cb(CLEAR_LINE); } TIMER_CALLBACK_MEMBER(mips_rambo_device::buzzer_toggle) @@ -150,9 +176,19 @@ u32 mips_rambo_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap { // check if dma channel is configured u32 const blocks_required = (screen.visible_area().height() * screen.visible_area().width()) >> 9; - if (!(m_channel[1].mode & MODE_CHANNEL_EN) || !(m_channel[1].mode & MODE_AUTO_RELOAD) || (m_channel[1].block_count != blocks_required)) + if (!(m_channel[1].mode & MODE_CHANNEL_EN) || (m_channel[1].reload_count != blocks_required)) return 1; + // screen is blanked unless auto reload is enabled + if (!(m_channel[1].mode & MODE_AUTO_RELOAD)) + { + m_channel[1].block_count = 0; + + return 0; + } + else + m_channel[1].block_count = m_channel[1].reload_count; + u32 address = m_channel[1].load_address; for (int y = screen.visible_area().min_y; y <= screen.visible_area().max_y; y++) for (int x = screen.visible_area().min_x; x <= screen.visible_area().max_x; x += 8) @@ -173,3 +209,35 @@ u32 mips_rambo_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap return 0; } + +template WRITE_LINE_MEMBER(mips_rambo_device::drq_w<0>); +template WRITE_LINE_MEMBER(mips_rambo_device::drq_w<1>); + +template WRITE_LINE_MEMBER(mips_rambo_device::drq_w) +{ + m_channel[Channel].drq_asserted = bool(state == ASSERT_LINE); + + while (m_channel[Channel].drq_asserted) + { + // check channel enabled + if (!(m_channel[Channel].mode & MODE_CHANNEL_EN)) + break; + + // TODO: check data remaining + + // FIXME: 16 bit dma + if (m_channel[Channel].mode & MODE_TO_MEMORY) + { + u8 const data = m_channel[Channel].read_cb(); + + m_ram->write(BYTE4_XOR_BE(m_channel[Channel].current_address), data); + } + else + { + u8 const data = m_ram->read(BYTE4_XOR_BE(m_channel[Channel].current_address)); + m_channel[Channel].write_cb(data); + } + + m_channel[Channel].current_address++; + } +} diff --git a/src/mame/machine/mips_rambo.h b/src/mame/machine/mips_rambo.h index 34a659ea319..f3703cbabc3 100644 --- a/src/mame/machine/mips_rambo.h +++ b/src/mame/machine/mips_rambo.h @@ -21,9 +21,12 @@ public: auto buzzer_out() { return m_buzzer_out_cb.bind(); } template void set_ram(T &&tag) { m_ram.set_tag(std::forward(tag)); } + template auto dma_r() { return m_channel[Channel].read_cb.bind(); } + template auto dma_w() { return m_channel[Channel].write_cb.bind(); } + // input lines template DECLARE_WRITE_LINE_MEMBER(irq_w) {} - template DECLARE_WRITE_LINE_MEMBER(drq_w) {} + template DECLARE_WRITE_LINE_MEMBER(drq_w); void map(address_map &map); u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); @@ -37,11 +40,27 @@ protected: template DECLARE_READ32_MEMBER(diag_r) { return 0; } template DECLARE_READ16_MEMBER(fifo_r) { return 0; } template DECLARE_READ32_MEMBER(mode_r) { return m_channel[Channel].mode; } - template DECLARE_READ16_MEMBER(block_count_r) { return m_channel[Channel].block_count; } - template DECLARE_READ32_MEMBER(current_address_r) { return 0; } + template DECLARE_READ16_MEMBER(block_count_r) + { + if ((Channel == 0) || !(m_channel[Channel].mode & MODE_CHANNEL_EN)) + return m_channel[0].block_count; + + /* + * HACK: The RISC/os boot sequence tests the dma channel 1 block count + * when configuring the monochrome graphics option. This hack simulates + * decrementing the block count for the video dma channel assuming a + * transfer of 1152x900 1-bit pixels at 72 Hz. With a device clock of + * 6.25 MHz, this is one block (64 bytes) approximately every 43 device + * cycles. + */ + u64 const block_cycles = attotime_to_clocks(machine().time()) / 43; + + return m_channel[Channel].block_count - (block_cycles % (m_channel[Channel].block_count + 1)); + } + template DECLARE_READ32_MEMBER(current_address_r) { return m_channel[Channel].current_address; } DECLARE_READ32_MEMBER(tcount_r); - DECLARE_READ32_MEMBER(tbreak_r) { return 0; } + DECLARE_READ32_MEMBER(tbreak_r) { return m_tbreak; } DECLARE_READ32_MEMBER(error_r) { return 0; } DECLARE_READ32_MEMBER(control_r) { return 0; } @@ -54,6 +73,7 @@ protected: DECLARE_WRITE32_MEMBER(tbreak_w); DECLARE_WRITE32_MEMBER(control_w); + TIMER_CALLBACK_MEMBER(timer); TIMER_CALLBACK_MEMBER(buzzer_toggle); private: @@ -73,6 +93,8 @@ private: MODE_DMA_ERROR = 0x00000200, // parity error during transfer MODE_DMA_INTR = 0x00000100, // channel interrupt pending MODE_COUNT_MASK = 0x000000ff, // halfword count bits + + MODE_WRITE_MASK = 0xff000000, }; enum control_mask : u32 @@ -97,16 +119,25 @@ private: u32 diag; u32 mode; u16 block_count; + u16 reload_count; u32 current_address; + + bool drq_asserted; + + // FIXME: 16 bit dma + devcb_read8 read_cb; + devcb_write8 write_cb; } m_channel[2]; + emu_timer *m_timer; emu_timer *m_buzzer_timer; int m_irq_out_state; int m_buzzer_out_state; attotime m_tcount; + u32 m_tbreak; }; DECLARE_DEVICE_TYPE(MIPS_RAMBO, mips_rambo_device)