mirror of
https://github.com/holub/mame
synced 2025-04-23 00:39:36 +03:00
mips: enough to panic (nw)
With these changes, RISC/os now loads and panics in kmemalloc(). * mips1: added fpa imp/revision numbers * mips: hack around prom bootp broadcast bug * rambo: timer/counter interrupt * rambo: enough dma to make scsi work * rambo: simulate RISC/os video dma test/init behaviour
This commit is contained in:
parent
82c91f7777
commit
f74ad668aa
@ -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; }
|
||||
|
@ -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<INT_KBD>)).invert();
|
||||
m_kbdc->kbd_irq().set(FUNC(rx3230_state::irq_w<INT_KBD>));
|
||||
|
||||
// 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);
|
||||
|
@ -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<r3000a_device> m_cpu;
|
||||
required_device<ram_device> m_ram;
|
||||
required_region_ptr<u32> m_rom;
|
||||
|
||||
// i/o devices
|
||||
required_device<mips_rambo_device> m_rambo;
|
||||
|
@ -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 <unsigned Channel> 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 <unsigned Channel> 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 <unsigned Channel> 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++;
|
||||
}
|
||||
}
|
||||
|
@ -21,9 +21,12 @@ public:
|
||||
auto buzzer_out() { return m_buzzer_out_cb.bind(); }
|
||||
template <typename T> void set_ram(T &&tag) { m_ram.set_tag(std::forward<T>(tag)); }
|
||||
|
||||
template <unsigned Channel> auto dma_r() { return m_channel[Channel].read_cb.bind(); }
|
||||
template <unsigned Channel> auto dma_w() { return m_channel[Channel].write_cb.bind(); }
|
||||
|
||||
// input lines
|
||||
template <unsigned Interrupt> DECLARE_WRITE_LINE_MEMBER(irq_w) {}
|
||||
template <unsigned Channel> DECLARE_WRITE_LINE_MEMBER(drq_w) {}
|
||||
template <unsigned Channel> 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 <unsigned Channel> DECLARE_READ32_MEMBER(diag_r) { return 0; }
|
||||
template <unsigned Channel> DECLARE_READ16_MEMBER(fifo_r) { return 0; }
|
||||
template <unsigned Channel> DECLARE_READ32_MEMBER(mode_r) { return m_channel[Channel].mode; }
|
||||
template <unsigned Channel> DECLARE_READ16_MEMBER(block_count_r) { return m_channel[Channel].block_count; }
|
||||
template <unsigned Channel> DECLARE_READ32_MEMBER(current_address_r) { return 0; }
|
||||
template <unsigned Channel> 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 <unsigned Channel> 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)
|
||||
|
Loading…
Reference in New Issue
Block a user