From 56af26b77aa5d564cefad4ae2f435ee155b1409d Mon Sep 17 00:00:00 2001 From: arbee Date: Mon, 20 Jan 2025 21:52:52 -0500 Subject: bus/nubus: Updates and minor cleanup [R. Belmont] - Refactored around an internal address space object so both 32 and 64-bit host machines just work - A few minor bits of cleanup/modernization apple/maclc.cpp: Patch macclas2's ROM to fix a verified-on-hardware illegal 68030 instruction that manages to work by accident. This fixes MAME showing a sad Mac after POST in 32-bit mode (pending determination of what the 68030 actually does). [Doug Brown, R. Belmont] --- src/devices/bus/nubus/nubus.cpp | 165 +++++++++++++++++++++------------------- src/devices/bus/nubus/nubus.h | 18 ++++- src/mame/apple/maclc.cpp | 19 +++++ src/mame/apple/macquadra605.cpp | 3 +- src/mame/apple/macquadra630.cpp | 1 + src/mame/apple/macquadra700.cpp | 1 + src/mame/apple/macquadra800.cpp | 1 + 7 files changed, 126 insertions(+), 82 deletions(-) diff --git a/src/devices/bus/nubus/nubus.cpp b/src/devices/bus/nubus/nubus.cpp index 0ca41acf8a6..89ef0d17c7b 100644 --- a/src/devices/bus/nubus/nubus.cpp +++ b/src/devices/bus/nubus/nubus.cpp @@ -65,20 +65,8 @@ void nubus_slot_device::device_start() { } -//************************************************************************** -// GLOBAL VARIABLES -//************************************************************************** - DEFINE_DEVICE_TYPE(NUBUS, nubus_device, "nubus", "NuBus") -//************************************************************************** -// LIVE DEVICE -//************************************************************************** - -//------------------------------------------------- -// nubus_device - constructor -//------------------------------------------------- - nubus_device::nubus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : nubus_device(mconfig, NUBUS, tag, owner, clock) { @@ -86,27 +74,55 @@ nubus_device::nubus_device(const machine_config &mconfig, const char *tag, devic nubus_device::nubus_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, type, tag, owner, clock), + device_memory_interface(mconfig, *this), m_space(*this, finder_base::DUMMY_TAG, -1), + m_mem_config("nubus", ENDIANNESS_BIG, 32, 32), m_out_irq9_cb(*this), m_out_irqa_cb(*this), m_out_irqb_cb(*this), m_out_irqc_cb(*this), m_out_irqd_cb(*this), - m_out_irqe_cb(*this) + m_out_irqe_cb(*this), + m_bus_mode(nubus_mode_t::NORMAL), + m_addr_mask(0xffffffff) { - m_addr_mask = 0xffffffff; } nubus_device::~nubus_device() { } -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- +device_memory_interface::space_config_vector nubus_device::memory_space_config() const +{ + return space_config_vector{ + std::make_pair(AS_DATA, &m_mem_config)}; +} void nubus_device::device_start() { + switch (m_bus_mode) + { + case nubus_mode_t::NORMAL: + m_space->install_read_handler(0x90000000, 0xefffffff, emu::rw_delegate(*this, FUNC(nubus_device::bus_memory_r<0x90000000>))); + m_space->install_write_handler(0x90000000, 0xefffffff, emu::rw_delegate(*this, FUNC(nubus_device::bus_memory_w<0x90000000>))); + m_space->install_read_handler(0xf9000000, 0xfeffffff, emu::rw_delegate(*this, FUNC(nubus_device::bus_memory_r<0xf9000000>))); + m_space->install_write_handler(0xf9000000, 0xfeffffff, emu::rw_delegate(*this, FUNC(nubus_device::bus_memory_w<0xf9000000>))); + break; + + case nubus_mode_t::QUADRA_DAFB: + m_space->install_read_handler(0xa0000000, 0xefffffff, emu::rw_delegate(*this, FUNC(nubus_device::bus_memory_r<0x90000000>))); + m_space->install_write_handler(0xa0000000, 0xefffffff, emu::rw_delegate(*this, FUNC(nubus_device::bus_memory_w<0x90000000>))); + m_space->install_read_handler(0xfa000000, 0xfeffffff, emu::rw_delegate(*this, FUNC(nubus_device::bus_memory_r<0xf9000000>))); + m_space->install_write_handler(0xfa000000, 0xfeffffff, emu::rw_delegate(*this, FUNC(nubus_device::bus_memory_w<0xf9000000>))); + break; + + case nubus_mode_t::LC_PDS: + m_space->install_read_handler(0x80e00000, 0x80ffffff, emu::rw_delegate(*this, FUNC(nubus_device::bus_memory_r<0x80e00000>))); + m_space->install_write_handler(0x80e00000, 0x80ffffff, emu::rw_delegate(*this, FUNC(nubus_device::bus_memory_w<0x80e00000>))); + m_space->install_read_handler(0x00e00000, 0x00efffff, emu::rw_delegate(*this, FUNC(nubus_device::bus_memory_r<0x80e00000>))); + m_space->install_write_handler(0x00e00000, 0x00efffff, emu::rw_delegate(*this, FUNC(nubus_device::bus_memory_w<0x80e00000>))); + break; + } } void nubus_device::add_nubus_card(device_nubus_card_interface &card) @@ -114,23 +130,39 @@ void nubus_device::add_nubus_card(device_nubus_card_interface &card) m_device_list.emplace_back(card); } +template +u32 nubus_device::bus_memory_r(offs_t offset, uint32_t mem_mask) +{ + return this->space(AS_DATA).read_dword(Base + (offset * 4), mem_mask); +} + +template +void nubus_device::bus_memory_w(offs_t offset, uint32_t data, uint32_t mem_mask) +{ + this->space(AS_DATA).write_dword(Base + (offset * 4), data, mem_mask); +} + +template uint32_t nubus_device::bus_memory_r<0x90000000>(offs_t offset, u32 mem_mask); +template void nubus_device::bus_memory_w<0x90000000>(offs_t offset, u32 data, u32 mem_mask); +template uint32_t nubus_device::bus_memory_r<0xf9000000>(offs_t offset, u32 mem_mask); +template void nubus_device::bus_memory_w<0xf9000000>(offs_t offset, u32 data, u32 mem_mask); + +template uint32_t nubus_device::bus_memory_r<0xa0000000>(offs_t offset, u32 mem_mask); +template void nubus_device::bus_memory_w<0xa0000000>(offs_t offset, u32 data, u32 mem_mask); +template uint32_t nubus_device::bus_memory_r<0xfa000000>(offs_t offset, u32 mem_mask); +template void nubus_device::bus_memory_w<0xfa000000>(offs_t offset, u32 data, u32 mem_mask); + +template uint32_t nubus_device::bus_memory_r<0x00e00000>(offs_t offset, u32 mem_mask); +template void nubus_device::bus_memory_w<0x00e00000>(offs_t offset, u32 data, u32 mem_mask); +template uint32_t nubus_device::bus_memory_r<0x80e00000>(offs_t offset, u32 mem_mask); +template void nubus_device::bus_memory_w<0x80e00000>(offs_t offset, u32 data, u32 mem_mask); + template void nubus_device::install_device(offs_t start, offs_t end, R rhandler, W whandler, uint32_t mask) { - const int buswidth = m_space->data_width(); start &= m_addr_mask; end &= m_addr_mask; - switch(buswidth) - { - case 32: - m_space->install_readwrite_handler(start, end, rhandler, whandler, mask); - break; - case 64: - m_space->install_readwrite_handler(start, end, rhandler, whandler, (uint64_t(mask) << 32) | mask); - break; - default: - fatalerror("NUBUS: Bus width %d not supported\n", buswidth); - } + space(AS_DATA).install_readwrite_handler(start, end, rhandler, whandler, mask); } template void nubus_device::install_device(offs_t start, offs_t end, read8_delegate rhandler, write8_delegate whandler, uint32_t mask); @@ -149,20 +181,9 @@ template void nubus_device::install_device void nubus_device::install_readonly_device(offs_t start, offs_t end, R rhandler, uint32_t mask) { - const int buswidth = m_space->data_width(); start &= m_addr_mask; end &= m_addr_mask; - switch(buswidth) - { - case 32: - m_space->install_read_handler(start, end, rhandler, mask); - break; - case 64: - m_space->install_read_handler(start, end, rhandler, (uint64_t(mask) << 32) | mask); - break; - default: - fatalerror("NUBUS: Bus width %d not supported\n", buswidth); - } + space(AS_DATA).install_read_handler(start, end, rhandler, mask); } template void nubus_device::install_readonly_device(offs_t start, offs_t end, read8_delegate rhandler, uint32_t mask); @@ -181,20 +202,9 @@ template void nubus_device::install_readonly_device(offs_t s template void nubus_device::install_writeonly_device(offs_t start, offs_t end, W whandler, uint32_t mask) { - const int buswidth = m_space->data_width(); start &= m_addr_mask; end &= m_addr_mask; - switch(buswidth) - { - case 32: - m_space->install_write_handler(start, end, whandler, mask); - break; - case 64: - m_space->install_write_handler(start, end, whandler, (uint64_t(mask) << 32) | mask); - break; - default: - fatalerror("NUBUS: Bus width %d not supported\n", buswidth); - } + space(AS_DATA).install_write_handler(start, end, whandler, mask); } template void nubus_device::install_writeonly_device(offs_t start, offs_t end, write8_delegate whandler, uint32_t mask); @@ -214,21 +224,23 @@ void nubus_device::install_bank(offs_t start, offs_t end, void *data) { start &= m_addr_mask; end &= m_addr_mask; - m_space->install_ram(start, end, data); + space(AS_DATA).install_ram(start, end, data); } void nubus_device::install_view(offs_t start, offs_t end, memory_view &view) { start &= m_addr_mask; end &= m_addr_mask; - m_space->install_view(start, end, view); + space(AS_DATA).install_view(start, end, view); } void nubus_device::set_irq_line(int slot, int state) { switch (slot) { - case 0x9: irq9_w(state); break; + case 0x9: + irq9_w(state); + break; case 0xa: irqa_w(state); break; case 0xb: irqb_w(state); break; case 0xc: irqc_w(state); break; @@ -277,7 +289,7 @@ device_nubus_card_interface::~device_nubus_card_interface() void device_nubus_card_interface::interface_pre_start() { - if ((!strncmp(m_nubus_slottag, "pds030", 6)) || (!strcmp(m_nubus_slottag, "siexp"))) + if ((!strncmp(m_nubus_slottag, "pds030", 6)) || (!strncmp(m_nubus_slottag, "siexp", 5))) { m_slot = 0x9; // '030 PDS slots phantom slot as whatever they want but default to 9 } @@ -347,13 +359,6 @@ void device_nubus_card_interface::install_declaration_rom(const char *romregion, inverted = true; } -#if 0 - FILE *f; - f = fopen("romout.bin", "wb"); - fwrite(rom, romlen, 1, f); - fclose(f); -#endif - switch (byteLanes) { case 0x0f: // easy case: all 4 lanes (still must scramble for 32-bit BE bus though) @@ -365,8 +370,8 @@ void device_nubus_card_interface::install_declaration_rom(const char *romregion, break; case 0xe1: // lane 0 only - m_declaration_rom.resize(romlen*4); - memset(&m_declaration_rom[0], 0, romlen*4); + m_declaration_rom.resize(romlen * 4); + std::fill_n(&m_declaration_rom[0], romlen * 4, 0); for (int i = 0; i < romlen; i++) { m_declaration_rom[BYTE4_XOR_BE(i*4)] = rom[i]; @@ -375,8 +380,8 @@ void device_nubus_card_interface::install_declaration_rom(const char *romregion, break; case 0xd2: // lane 1 only - m_declaration_rom.resize(romlen*4); - memset(&m_declaration_rom[0], 0, romlen*4); + m_declaration_rom.resize(romlen * 4); + std::fill_n(&m_declaration_rom[0], romlen * 4, 0); for (int i = 0; i < romlen; i++) { m_declaration_rom[BYTE4_XOR_BE((i*4)+1)] = rom[i]; @@ -385,8 +390,8 @@ void device_nubus_card_interface::install_declaration_rom(const char *romregion, break; case 0xb4: // lane 2 only - m_declaration_rom.resize(romlen*4); - memset(&m_declaration_rom[0], 0, romlen*4); + m_declaration_rom.resize(romlen * 4); + std::fill_n(&m_declaration_rom[0], romlen * 4, 0); for (int i = 0; i < romlen; i++) { m_declaration_rom[BYTE4_XOR_BE((i*4)+2)] = rom[i]; @@ -395,8 +400,8 @@ void device_nubus_card_interface::install_declaration_rom(const char *romregion, break; case 0x78: // lane 3 only - m_declaration_rom.resize(romlen*4); - memset(&m_declaration_rom[0], 0, romlen*4); + m_declaration_rom.resize(romlen * 4); + std::fill_n(&m_declaration_rom[0], romlen * 4, 0); for (int i = 0; i < romlen; i++) { m_declaration_rom[BYTE4_XOR_BE((i*4)+3)] = rom[i]; @@ -405,9 +410,9 @@ void device_nubus_card_interface::install_declaration_rom(const char *romregion, break; case 0xc3: // lanes 0, 1 - m_declaration_rom.resize(romlen*2); - memset(&m_declaration_rom[0], 0, romlen*2); - for (int i = 0; i < romlen/2; i++) + m_declaration_rom.resize(romlen * 2); + std::fill_n(&m_declaration_rom[0], romlen * 2, 0); + for (int i = 0; i < romlen / 2; i++) { m_declaration_rom[BYTE4_XOR_BE((i*4)+0)] = rom[(i*2)]; m_declaration_rom[BYTE4_XOR_BE((i*4)+1)] = rom[(i*2)+1]; @@ -416,8 +421,8 @@ void device_nubus_card_interface::install_declaration_rom(const char *romregion, break; case 0xa5: // lanes 0, 2 - m_declaration_rom.resize(romlen*2); - memset(&m_declaration_rom[0], 0, romlen*2); + m_declaration_rom.resize(romlen * 2); + std::fill_n(&m_declaration_rom[0], romlen * 2, 0); for (int i = 0; i < romlen/2; i++) { m_declaration_rom[BYTE4_XOR_BE((i*4)+0)] = rom[(i*2)]; @@ -427,8 +432,8 @@ void device_nubus_card_interface::install_declaration_rom(const char *romregion, break; case 0x3c: // lanes 2,3 - m_declaration_rom.resize(romlen*2); - memset(&m_declaration_rom[0], 0, romlen*2); + m_declaration_rom.resize(romlen * 2); + std::fill_n(&m_declaration_rom[0], romlen * 2, 0); for (int i = 0; i < romlen/2; i++) { m_declaration_rom[BYTE4_XOR_BE((i*4)+2)] = rom[(i*2)]; @@ -438,7 +443,7 @@ void device_nubus_card_interface::install_declaration_rom(const char *romregion, break; default: - fatalerror("NuBus: unhandled byteLanes value %02x\n", byteLanes); + fatalerror("nubus: unhandled byteLanes value %02x\n", byteLanes); } // the slot manager can supposedly handle inverted ROMs by itself, but let's do it for it anyway diff --git a/src/devices/bus/nubus/nubus.h b/src/devices/bus/nubus/nubus.h index e01a88adbb0..f2a8bd7f853 100644 --- a/src/devices/bus/nubus/nubus.h +++ b/src/devices/bus/nubus/nubus.h @@ -106,7 +106,7 @@ DECLARE_DEVICE_TYPE(NUBUS_SLOT, nubus_slot_device) class device_nubus_card_interface; // ======================> nubus_device -class nubus_device : public device_t +class nubus_device : public device_t, public device_memory_interface { public: // construction/destruction @@ -122,6 +122,14 @@ public: auto out_irqd_callback() { return m_out_irqd_cb.bind(); } auto out_irqe_callback() { return m_out_irqe_cb.bind(); } + typedef enum NUBUS_MODE_T + { + NORMAL = 0, + QUADRA_DAFB, // omits slot 9 space + LC_PDS // takes slot $E space only, with A31 in both states, for V8 based systems + } nubus_mode_t; + void set_bus_mode(nubus_mode_t newMode) { m_bus_mode = newMode; } + void add_nubus_card(device_nubus_card_interface &card); template void install_device(offs_t start, offs_t end, R rhandler, W whandler, uint32_t mask=0xffffffff); template void install_readonly_device(offs_t start, offs_t end, R rhandler, uint32_t mask=0xffffffff); @@ -144,9 +152,16 @@ protected: // device_t implementation virtual void device_start() override ATTR_COLD; + virtual space_config_vector memory_space_config() const override; + + template uint32_t bus_memory_r(offs_t offset, uint32_t mem_mask); + template void bus_memory_w(offs_t offset, uint32_t data, uint32_t mem_mask); + // internal state required_address_space m_space; + address_space_config m_mem_config; + devcb_write_line m_out_irq9_cb; devcb_write_line m_out_irqa_cb; devcb_write_line m_out_irqb_cb; @@ -156,6 +171,7 @@ protected: std::vector > m_device_list; + nubus_mode_t m_bus_mode; uint32_t m_addr_mask; }; diff --git a/src/mame/apple/maclc.cpp b/src/mame/apple/maclc.cpp index 1e2717a6758..422aa1ca682 100644 --- a/src/mame/apple/maclc.cpp +++ b/src/mame/apple/maclc.cpp @@ -404,6 +404,7 @@ void maclc_state::maclc_base(machine_config &config) nubus_device &nubus(NUBUS(config, "pds", 0)); nubus.set_space(m_maincpu, AS_PROGRAM); nubus.set_address_mask(0x80ffffff); + nubus.set_bus_mode(nubus_device::nubus_mode_t::LC_PDS); // V8 supports interrupts for slots $C, $D, and $E, but the LC, LC II, and Color Classic // only hook the slot $E IRQ up to the PDS slot. ($C/$D/$E are 0/1/2 on the schematics). nubus.out_irqe_callback().set(m_v8, FUNC(v8_device::slot2_irq_w)); @@ -601,6 +602,24 @@ ROM_START( macclas2 ) ROM_LOAD32_BYTE( "341-0866__5be9__=c=apple_91.rommh.27c010.u24", 0x000001, 0x020000, CRC(eae68c36) SHA1(e6ce79647dfe7e66590a012836d0b6e985ff672b) ) ROM_LOAD32_BYTE( "341-0865__821e__=c=apple_91.romml.27c010.u23", 0x000002, 0x020000, CRC(cb306c01) SHA1(4d6e409995fd9a4aa9afda0fd790a5b09b1c2aca) ) ROM_LOAD32_BYTE( "341-0864__6fc6__=c=apple_91.romll.27c010.u22", 0x000003, 0x020000, CRC(21a51e72) SHA1(bb513c1a5b8a41c7534d66aeacaeea47f58dae92) ) + + /* + There is a genuine bug in this ROM where a JMP through a table uses an index past the size of the + table and the processor ends up in the middle of another instruction. On a real 68030, the resulting + illegal instruction does some still-not-100%-understood things to the registers that cause things to + work by accident. While that is still being investigated, we can at least patch the ROM so that + booting when the system is in 32-bit mode works properly. + + This first patch changes the bad table JMP to an RTS; the ROM in the IIvx and IIvi has the correct + number of table entries for the Classic II's boxflag and shows that the desired result is to do + nothing. + */ + ROM_FILL(0x43b6e, 1, 0x4e) + ROM_FILL(0x43b6f, 1, 0x75) + + // This second patch fixes the ROM checksum to compensate for the patch we just made. + ROM_FILL(0x00002, 1, 0x66) + ROM_FILL(0x00003, 1, 0x88) ROM_END ROM_START(maccclas) diff --git a/src/mame/apple/macquadra605.cpp b/src/mame/apple/macquadra605.cpp index ca036edaeaa..5dd7526e24b 100644 --- a/src/mame/apple/macquadra605.cpp +++ b/src/mame/apple/macquadra605.cpp @@ -1,5 +1,5 @@ -// license:BSD-3-Clause // copyright-holders:R. Belmont +// license:BSD-3-Clause /**************************************************************************** drivers/macquadra605.cpp @@ -225,6 +225,7 @@ void quadra605_state::macqd605(machine_config &config) nubus_device &nubus(NUBUS(config, "pds", 0)); nubus.set_space(m_maincpu, AS_PROGRAM); + nubus.set_bus_mode(nubus_device::nubus_mode_t::QUADRA_DAFB); nubus.out_irqe_callback().set(m_primetime, FUNC(primetime_device::via2_irq_w<0x20>)); NUBUS_SLOT(config, "lcpds", "pds", mac_pdslc_cards, nullptr); diff --git a/src/mame/apple/macquadra630.cpp b/src/mame/apple/macquadra630.cpp index a14662bebde..16117d837f8 100644 --- a/src/mame/apple/macquadra630.cpp +++ b/src/mame/apple/macquadra630.cpp @@ -197,6 +197,7 @@ void quadra630_state::macqd630(machine_config &config) nubus_device &nubus(NUBUS(config, "pds", 0)); nubus.set_space(m_maincpu, AS_PROGRAM); + nubus.set_bus_mode(nubus_device::nubus_mode_t::QUADRA_DAFB); nubus.out_irqe_callback().set(m_primetimeii, FUNC(primetime_device::via2_irq_w<0x20>)); NUBUS_SLOT(config, "lcpds", "pds", mac_pdslc_cards, nullptr); diff --git a/src/mame/apple/macquadra700.cpp b/src/mame/apple/macquadra700.cpp index 1cfbe1b7946..a18c140fb1a 100644 --- a/src/mame/apple/macquadra700.cpp +++ b/src/mame/apple/macquadra700.cpp @@ -778,6 +778,7 @@ void eclipse_state::via2_out_b_q900(u8 data) nubus_device &nubus(NUBUS(config, "nubus", 40_MHz_XTAL / 4)); nubus.set_space(m_maincpu, AS_PROGRAM); + nubus.set_bus_mode(nubus_device::nubus_mode_t::QUADRA_DAFB); nubus.out_irq9_callback().set(FUNC(quadrax00_state::nubus_irq_9_w)); nubus.out_irqa_callback().set(FUNC(quadrax00_state::nubus_irq_a_w)); nubus.out_irqb_callback().set(FUNC(quadrax00_state::nubus_irq_b_w)); diff --git a/src/mame/apple/macquadra800.cpp b/src/mame/apple/macquadra800.cpp index 12d8e2ef482..9e733f77efb 100644 --- a/src/mame/apple/macquadra800.cpp +++ b/src/mame/apple/macquadra800.cpp @@ -247,6 +247,7 @@ void quadra800_state::macqd800(machine_config &config) nubus_device &nubus(NUBUS(config, "nubus", 40_MHz_XTAL / 4)); nubus.set_space(m_maincpu, AS_PROGRAM); + nubus.set_bus_mode(nubus_device::nubus_mode_t::QUADRA_DAFB); nubus.out_irqc_callback().set(m_iosb, FUNC(iosb_device::via2_irq_w<0x08>)); nubus.out_irqd_callback().set(m_iosb, FUNC(iosb_device::via2_irq_w<0x10>)); nubus.out_irqe_callback().set(m_iosb, FUNC(iosb_device::via2_irq_w<0x20>)); -- cgit v1.2.3