diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua index e3bcc75c45d..c7a038195ec 100644 --- a/scripts/src/machine.lua +++ b/scripts/src/machine.lua @@ -2779,6 +2779,8 @@ if (MACHINES["PCI"]~=null) then MAME_DIR .. "src/devices/machine/lpc-rtc.h", MAME_DIR .. "src/devices/machine/lpc-pit.cpp", MAME_DIR .. "src/devices/machine/lpc-pit.h", + MAME_DIR .. "src/devices/machine/mpc106.cpp", + MAME_DIR .. "src/devices/machine/mpc106.h", MAME_DIR .. "src/devices/machine/vrc4373.cpp", MAME_DIR .. "src/devices/machine/vrc4373.h", MAME_DIR .. "src/devices/machine/vrc5074.cpp", diff --git a/src/devices/machine/mpc106.cpp b/src/devices/machine/mpc106.cpp new file mode 100644 index 00000000000..ba142f83fc4 --- /dev/null +++ b/src/devices/machine/mpc106.cpp @@ -0,0 +1,246 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont +/********************************************************************** + + mpc106.cpp - Motorola MPC106 PCI host bridge, aka "Grackle". + + Can support up to 4 PowerPC CPUs, up to 1 GiB of RAM, and 16 MiB of ROM + +**********************************************************************/ +#include "emu.h" +#include "mpc106.h" + +enum +{ + AS_PCI_MEM = 1, + AS_PCI_IO = 2 +}; + +DEFINE_DEVICE_TYPE(MPC106, mpc106_host_device, "mpc106", "Motorola MPC106 PCI Bridge/Memory Controller") + +void mpc106_host_device::config_map(address_map &map) +{ + pci_host_device::config_map(map); + map(0x70, 0x71).rw(FUNC(mpc106_host_device::pwrconfig1_r), FUNC(mpc106_host_device::pwrconfig1_w)); + map(0x72, 0x72).rw(FUNC(mpc106_host_device::pwrconfig2_r), FUNC(mpc106_host_device::pwrconfig2_w)); +} + +mpc106_host_device::mpc106_host_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : pci_host_device(mconfig, MPC106, tag, owner, clock) + , m_mem_config("memory_space", ENDIANNESS_LITTLE, 32, 32) + , m_io_config("io_space", ENDIANNESS_LITTLE, 32, 32) + , m_cpu(*this, finder_base::DUMMY_TAG) +{ + set_ids_host(0x10570002, 0x40, 0x000006); +} + +void mpc106_host_device::set_ram_size(int _ram_size) +{ + m_ram_size = _ram_size; +} + +void mpc106_host_device::set_rom_tag(const char *tag) +{ + m_rom_tag = tag; +} + +void mpc106_host_device::set_map_type(map_type maptype) +{ + m_map_type = maptype; +} + +void mpc106_host_device::device_start() +{ + pci_host_device::device_start(); + m_cpu_space = &m_cpu->space(AS_PCI_CONFIG); + memory_space = &space(AS_PCI_MEM); + io_space = &space(AS_PCI_IO); + + memory_window_start = 0; + memory_window_end = 0xffffffff; + memory_offset = 0; + io_window_start = 0; + io_window_end = 0xffffffff; + io_offset = 0; + command = 0x0006; + status = 0x0080; + + m_rom = device().machine().root_device().memregion(m_rom_tag)->base(); + m_rom_size = device().machine().root_device().memregion(m_rom_tag)->bytes(); + + m_ram.resize(m_ram_size/4); + + m_pwrconfig1 = m_pwrconfig2 = 0; + m_last_config_address = -1; + + u64 rom_base = 0x100000000ULL - m_rom_size; + m_cpu_space->install_rom(rom_base, 0xffffffff, m_rom); + + if (m_map_type == MAP_TYPE_A) + { // type A is PReP + m_cpu_space->install_read_handler (0x80000000, 0x807fffff, read32s_delegate(*this, FUNC(mpc106_host_device::pci_io_r<0>))); + m_cpu_space->install_write_handler(0x80000000, 0x807fffff, write32s_delegate(*this, FUNC(mpc106_host_device::pci_io_w<0>))); + + m_cpu_space->install_device(0x80000000, 0x80000cff, *static_cast(this), &pci_host_device::io_configuration_access_map); + + m_cpu_space->install_read_handler (0x81000000, 0xbf7fffff, read32s_delegate(*this, FUNC(mpc106_host_device::pci_io_r<0x01000000>))); + m_cpu_space->install_write_handler(0x81000000, 0xbf7fffff, write32s_delegate(*this, FUNC(mpc106_host_device::pci_io_w<0x01000000>))); + m_cpu_space->install_read_handler (0xc0000000, 0xfeffffff, read32s_delegate(*this, FUNC(mpc106_host_device::pci_memory_r<0>))); + m_cpu_space->install_write_handler(0xc0000000, 0xfeffffff, write32s_delegate(*this, FUNC(mpc106_host_device::pci_memory_w<0>))); + } + else if (m_map_type == MAP_TYPE_B) + { // type B is CHRP + m_cpu_space->install_read_handler (0x80000000, 0xfcffffff, read32s_delegate(*this, FUNC(mpc106_host_device::pci_memory_r<0x80000000>))); + m_cpu_space->install_write_handler(0x80000000, 0xfcffffff, write32s_delegate(*this, FUNC(mpc106_host_device::pci_memory_w<0x80000000>))); + m_cpu_space->install_read_handler (0xfd000000, 0xfdffffff, read32s_delegate(*this, FUNC(mpc106_host_device::pci_memory_r<0>))); + m_cpu_space->install_write_handler(0xfd000000, 0xfdffffff, write32s_delegate(*this, FUNC(mpc106_host_device::pci_memory_w<0>))); + m_cpu_space->install_read_handler (0xfe000000, 0xfe00ffff, read32s_delegate(*this, FUNC(mpc106_host_device::pci_io_r<0>))); + m_cpu_space->install_write_handler(0xfe000000, 0xfe00ffff, write32s_delegate(*this, FUNC(mpc106_host_device::pci_io_w<0>))); + m_cpu_space->install_read_handler (0xfe800000, 0xfebfffff, read32s_delegate(*this, FUNC(mpc106_host_device::pci_io_r<0x00800000>))); + m_cpu_space->install_write_handler(0xfe800000, 0xfebfffff, write32s_delegate(*this, FUNC(mpc106_host_device::pci_io_w<0x00800000>))); + + m_cpu_space->install_device(0xfec00000, 0xfeefffff, *static_cast(this), &mpc106_host_device::access_map); + } +} + +device_memory_interface::space_config_vector mpc106_host_device::memory_space_config() const +{ + auto r = pci_bridge_device::memory_space_config(); + r.emplace_back(std::make_pair(AS_PCI_MEM, &m_mem_config)); + r.emplace_back(std::make_pair(AS_PCI_IO, &m_io_config)); + return r; +} + +void mpc106_host_device::reset_all_mappings() +{ + pci_host_device::reset_all_mappings(); +} + +void mpc106_host_device::device_reset() +{ + pci_host_device::device_reset(); + m_last_config_address = -1; +} + +void mpc106_host_device::access_map(address_map &map) +{ + map(0x00000000, 0x001fffff).rw(FUNC(mpc106_host_device::be_config_address_r), FUNC(mpc106_host_device::be_config_address_w)); + map(0x00200000, 0x002fffff).rw(FUNC(mpc106_host_device::be_config_data_r), FUNC(mpc106_host_device::be_config_data_w)); +} + +u32 mpc106_host_device::be_config_address_r() +{ + u32 temp = pci_host_device::config_address_r(); + return (temp>>24) | (temp<<24) | ((temp & 0xff00) << 8) | ((temp & 0xff0000) >> 8); +} + +void mpc106_host_device::be_config_address_w(offs_t offset, u32 data, u32 mem_mask) +{ + u32 tempdata; + + //printf("config_address_w: %08x mask %08x\n", data, mem_mask); + + tempdata = (data >> 24) | (data << 24) | ((data & 0xff00) << 8) | ((data & 0xff0000) >> 8); + pci_host_device::config_address_w(offset, tempdata, mem_mask); + m_last_config_address = tempdata & 0xffffff00; +} + +u32 mpc106_host_device::be_config_data_r(offs_t offset, u32 mem_mask) +{ + // config registers inside the MPC106 itself are little-endian and must be flipped if the host CPU is BE. + // TODO: we just assume a BE host CPU for now. + if (m_last_config_address == 0x80000000) + { + return pci_host_device::config_data_r(offset, mem_mask); + } + else + { + u32 temp = pci_host_device::config_data_r(offset, mem_mask); + return (temp >> 24) | (temp << 24) | ((temp & 0xff00) << 8) | ((temp & 0xff0000) >> 8); + } +} + +void mpc106_host_device::be_config_data_w(offs_t offset, u32 data, u32 mem_mask) +{ + if (m_last_config_address == 0x80000000) + { + pci_host_device::config_data_w(offset, data, mem_mask); + } + else + { + u32 tempdata; + + //printf("config_data_w: %08x mask %08x\n", data, mem_mask); + + tempdata = (data >> 24) | (data << 24) | ((data & 0xff00) << 8) | ((data & 0xff0000) >> 8); + pci_host_device::config_data_w(offset, tempdata, mem_mask); + } +} + +template +u32 mpc106_host_device::pci_memory_r(offs_t offset, u32 mem_mask) +{ + u32 result = this->space(AS_PCI_MEM).read_dword(Base + (offset * 4), mem_mask); + return result; +} + +template +void mpc106_host_device::pci_memory_w(offs_t offset, u32 data, u32 mem_mask) +{ + this->space(AS_PCI_MEM).write_dword(Base + (offset * 4), data, mem_mask); +} + +template u32 mpc106_host_device::pci_memory_r<0>(offs_t offset, u32 mem_mask); +template u32 mpc106_host_device::pci_memory_r<0x80000000>(offs_t offset, u32 mem_mask); + +template void mpc106_host_device::pci_memory_w<0>(offs_t offset, u32 data, u32 mem_mask); +template void mpc106_host_device::pci_memory_w<0x80000000>(offs_t offset, u32 data, u32 mem_mask); + +template +u32 mpc106_host_device::pci_io_r(offs_t offset, u32 mem_mask) +{ + u32 result = this->space(AS_PCI_IO).read_dword(Base + (offset * 4), mem_mask); + return result; +} + +template +void mpc106_host_device::pci_io_w(offs_t offset, u32 data, u32 mem_mask) +{ + this->space(AS_PCI_IO).write_dword(Base + (offset * 4), data, mem_mask); +} + +template u32 mpc106_host_device::pci_io_r<0>(offs_t offset, u32 mem_mask); +template u32 mpc106_host_device::pci_io_r<0x01000000>(offs_t offset, u32 mem_mask); +template u32 mpc106_host_device::pci_io_r<0x00800000>(offs_t offset, u32 mem_mask); + +template void mpc106_host_device::pci_io_w<0>(offs_t offset, u32 data, u32 mem_mask); +template void mpc106_host_device::pci_io_w<0x01000000>(offs_t offset, u32 data, u32 mem_mask); +template void mpc106_host_device::pci_io_w<0x00800000>(offs_t offset, u32 data, u32 mem_mask); + +// map PCI memory and I/O space stuff here +void mpc106_host_device::map_extra(u64 memory_window_start, u64 memory_window_end, u64 memory_offset, address_space *memory_space, + u64 io_window_start, u64 io_window_end, u64 io_offset, address_space *io_space) +{ + u64 rom_base = 0x100000000ULL - m_rom_size; + memory_space->install_rom(rom_base, 0xffffffff, m_rom); +} + +u16 mpc106_host_device::pwrconfig1_r() +{ + return m_pwrconfig1; +} + +void mpc106_host_device::pwrconfig1_w(offs_t offset, u16 data, u16 mem_mask) +{ + COMBINE_DATA(&m_pwrconfig1); +} + +u8 mpc106_host_device::pwrconfig2_r() +{ + return m_pwrconfig2; +} + +void mpc106_host_device::pwrconfig2_w(offs_t offset, u8 data) +{ + m_pwrconfig2 = data; +} diff --git a/src/devices/machine/mpc106.h b/src/devices/machine/mpc106.h new file mode 100644 index 00000000000..b79d51dba58 --- /dev/null +++ b/src/devices/machine/mpc106.h @@ -0,0 +1,86 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont +/********************************************************************** + + mpc106.h - Motorola MPC-106 PCI host bridge, aka "Grackle". + +**********************************************************************/ + +#ifndef MAME_MACHINE_MPC106_H +#define MAME_MACHINE_MPC106_H + +#pragma once + +#include "pci.h" + +class mpc106_host_device : public pci_host_device { +public: + typedef enum + { + MAP_TYPE_A, // Type A is PowerPC Reference Platform (PReP) + MAP_TYPE_B // Type B is Common Hardware Reference Platform (CHRP) + } map_type; + + template + mpc106_host_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, map_type map, T &&cpu_tag, const char *rom_tag, int ram_size) + : mpc106_host_device(mconfig, tag, owner, clock) + { + set_ids_host(0x10570002, 0x00, 0x00000000); + set_map_type(map); + set_cpu_tag(std::forward(cpu_tag)); + set_rom_tag(rom_tag); + set_ram_size(ram_size); + } + mpc106_host_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + + template void set_cpu_tag(T &&tag) { m_cpu.set_tag(std::forward(tag)); } + void set_ram_size(int ram_size); + void set_rom_tag(const char *tag); + void set_map_type(map_type maptype); + +protected: + virtual void device_start() override; + virtual void device_reset() override; + + virtual void reset_all_mappings() override; + + virtual void map_extra(u64 memory_window_start, u64 memory_window_end, u64 memory_offset, address_space *memory_space, + u64 io_window_start, u64 io_window_end, u64 io_offset, address_space *io_space) override; + + virtual void config_map(address_map &map) override; + + virtual space_config_vector memory_space_config() const override; + +private: + void access_map(address_map &map); + u32 be_config_address_r(); + void be_config_address_w(offs_t offset, u32 data, u32 mem_mask = ~0); + u32 be_config_data_r(offs_t offset, u32 mem_mask = ~0); + void be_config_data_w(offs_t offset, u32 data, u32 mem_mask = ~0); + template u32 pci_memory_r(offs_t offset, u32 mem_mask); + template void pci_memory_w(offs_t offset, u32 data, u32 mem_mask); + template u32 pci_io_r(offs_t offset, u32 mem_mask); + template void pci_io_w(offs_t offset, u32 data, u32 mem_mask); + + u16 pwrconfig1_r(); + void pwrconfig1_w(offs_t offset, u16 data, u16 mem_mask); + u8 pwrconfig2_r(); + void pwrconfig2_w(offs_t offset, u8 data); + + address_space_config m_mem_config, m_io_config; + const char *m_rom_tag; + int m_ram_size; + map_type m_map_type; + required_device m_cpu; + std::vector m_ram; + u8 *m_rom; + u32 m_rom_size; + address_space *m_cpu_space; + u16 m_pwrconfig1; + u8 m_pwrconfig2; + u32 m_last_config_address; +}; + +DECLARE_DEVICE_TYPE(MPC106, mpc106_host_device) + +#endif // MAME_MACHINE_MPC106_H diff --git a/src/mame/apple/heathrow.cpp b/src/mame/apple/heathrow.cpp new file mode 100644 index 00000000000..e77f5159bd0 --- /dev/null +++ b/src/mame/apple/heathrow.cpp @@ -0,0 +1,401 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont +/* + Apple "Heathrow" and "Paddington" PCI ASICs + Emulation by R. Belmont + + These ASICs sit on the PCI bus and provide "legacy" Mac I/O, + including: + - A VIA to interface with Cuda + - Serial + - SWIM3 floppy + - MESH SCSI ("Macintosh Enhanced SCSI Handler"), a 5394/96 clone with some features Apple didn't use removed) + - ATA + - Ethernet (10 Mbps for Heathrow, 10/100 for Paddington) + - Audio + - Descriptor-based DMA engine, as originally seen in the "PDM" Power Macs +*/ + +#include "emu.h" +#include "heathrow.h" + +#include "bus/rs232/rs232.h" +#include "formats/ap_dsk35.h" + +static constexpr u32 C7M = 7833600; +static constexpr u32 C15M = (C7M * 2); + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +DEFINE_DEVICE_TYPE(HEATHROW, heathrow_device, "heathrow", "Apple Heathrow PCI I/O ASIC") +DEFINE_DEVICE_TYPE(PADDINGTON, paddington_device, "paddington", "Apple Paddington PCI I/O ASIC") + +//------------------------------------------------- +// ADDRESS_MAP +//------------------------------------------------- +/* + A "Kanga" G3 PowerBook says: + F3016000 : VIA + F3012000 : SCC Rd + F3012000 : SCC Wr + F3015000 : IWM/SWIM + F3010000 : SCSI + + ATA is at 20000 +*/ +void heathrow_device::map(address_map &map) +{ + map(0x00000, 0x00fff).rw(FUNC(heathrow_device::macio_r), FUNC(heathrow_device::macio_w)); + map(0x12000, 0x12fff).rw(FUNC(heathrow_device::scc_r), FUNC(heathrow_device::scc_w)); + map(0x13000, 0x13fff).rw(FUNC(heathrow_device::scc_macrisc_r), FUNC(heathrow_device::scc_macrisc_w)); + map(0x14000, 0x1401f).rw(m_awacs, FUNC(awacs_device::read), FUNC(awacs_device::write)); + map(0x15000, 0x15fff).rw(FUNC(heathrow_device::fdc_r), FUNC(heathrow_device::fdc_w)); + map(0x16000, 0x17fff).rw(FUNC(heathrow_device::mac_via_r), FUNC(heathrow_device::mac_via_w)); + map(0x60000, 0x7ffff).rw(FUNC(heathrow_device::nvram_r), FUNC(heathrow_device::nvram_w)); +} + +//------------------------------------------------- +// device_add_mconfig - add device configuration +//------------------------------------------------- +void heathrow_device::device_add_mconfig(machine_config &config) +{ + R65NC22(config, m_via1, C7M / 10); + m_via1->readpa_handler().set(FUNC(heathrow_device::via_in_a)); + m_via1->readpb_handler().set(FUNC(heathrow_device::via_in_b)); + m_via1->writepa_handler().set(FUNC(heathrow_device::via_out_a)); + m_via1->writepb_handler().set(FUNC(heathrow_device::via_out_b)); + m_via1->cb2_handler().set(FUNC(heathrow_device::via_out_cb2)); + m_via1->irq_handler().set(FUNC(heathrow_device::via1_irq)); + + AWACS(config, m_awacs, 45.1584_MHz_XTAL / 2); + + SPEAKER(config, "lspeaker").front_left(); + SPEAKER(config, "rspeaker").front_right(); + m_awacs->add_route(0, "lspeaker", 1.0); + m_awacs->add_route(1, "rspeaker", 1.0); + + SWIM3(config, m_fdc, C15M); + m_fdc->devsel_cb().set(FUNC(heathrow_device::devsel_w)); + m_fdc->phases_cb().set(FUNC(heathrow_device::phases_w)); + + applefdintf_device::add_35_hd(config, m_floppy[0]); + applefdintf_device::add_35_nc(config, m_floppy[1]); + + SCC85C30(config, m_scc, C7M); + m_scc->configure_channels(3'686'400, 3'686'400, 3'686'400, 3'686'400); + m_scc->out_txda_callback().set("printer", FUNC(rs232_port_device::write_txd)); + m_scc->out_txdb_callback().set("modem", FUNC(rs232_port_device::write_txd)); + + rs232_port_device &rs232a(RS232_PORT(config, "printer", default_rs232_devices, nullptr)); + rs232a.rxd_handler().set(m_scc, FUNC(z80scc_device::rxa_w)); + rs232a.dcd_handler().set(m_scc, FUNC(z80scc_device::dcda_w)); + rs232a.cts_handler().set(m_scc, FUNC(z80scc_device::ctsa_w)); + + rs232_port_device &rs232b(RS232_PORT(config, "modem", default_rs232_devices, nullptr)); + rs232b.rxd_handler().set(m_scc, FUNC(z80scc_device::rxb_w)); + rs232b.dcd_handler().set(m_scc, FUNC(z80scc_device::dcdb_w)); + rs232b.cts_handler().set(m_scc, FUNC(z80scc_device::ctsb_w)); +} + +void heathrow_device::config_map(address_map &map) +{ + pci_device::config_map(map); +} + +//------------------------------------------------- +// heathrow_device - constructor +//------------------------------------------------- + +heathrow_device::heathrow_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) + : pci_device(mconfig, type, tag, owner, clock), + write_pb4(*this), + write_pb5(*this), + write_cb2(*this), + read_pb3(*this), + m_maincpu(*this, finder_base::DUMMY_TAG), + m_via1(*this, "via1"), + m_fdc(*this, "fdc"), + m_floppy(*this, "fdc:%d", 0U), + m_awacs(*this, "awacs"), + m_scc(*this, "scc"), + m_cur_floppy(nullptr), + m_hdsel(0) +{ + set_ids(0x106b0010, 0x01, 0xff000001, 0x000000); +} + +heathrow_device::heathrow_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : heathrow_device(mconfig, HEATHROW, tag, owner, clock) +{ +} + +paddington_device::paddington_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : heathrow_device(mconfig, PADDINGTON, tag, owner, clock) +{ +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void heathrow_device::common_init() +{ + write_pb4.resolve_safe(); + write_pb5.resolve_safe(); + write_cb2.resolve_safe(); + read_pb3.resolve_safe(0); + + m_6015_timer = timer_alloc(FUNC(heathrow_device::mac_6015_tick), this); + m_6015_timer->adjust(attotime::never); + save_item(NAME(m_hdsel)); + + add_map(0x80000, M_MEM, FUNC(heathrow_device::map)); + command = 2; // enable our memory range +} + +void heathrow_device::device_start() +{ + common_init(); +} + +void paddington_device::device_start() +{ + common_init(); +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void heathrow_device::device_reset() +{ + // start 60.15 Hz timer + m_6015_timer->adjust(attotime::from_hz(60.15), 0, attotime::from_hz(60.15)); + + m_hdsel = 0; +} + +TIMER_CALLBACK_MEMBER(heathrow_device::mac_6015_tick) +{ + m_via1->write_ca1(CLEAR_LINE); + m_via1->write_ca1(ASSERT_LINE); +} + +u8 heathrow_device::via_in_a() +{ + return 0x80; +} + +u8 heathrow_device::via_in_b() +{ + return read_pb3() << 3; +} + +WRITE_LINE_MEMBER(heathrow_device::via_out_cb2) +{ + write_cb2(state & 1); +} + +void heathrow_device::via_out_a(u8 data) +{ + int hdsel = BIT(data, 5); + if (hdsel != m_hdsel) + { + if (m_cur_floppy) + { + m_cur_floppy->ss_w(hdsel); + } + } + m_hdsel = hdsel; +} + +void heathrow_device::via_out_b(u8 data) +{ + write_pb4(BIT(data, 4)); + write_pb5(BIT(data, 5)); +} + +WRITE_LINE_MEMBER(heathrow_device::via1_irq) +{ +} + +WRITE_LINE_MEMBER(heathrow_device::cb1_w) +{ + m_via1->write_cb1(state); +} + +WRITE_LINE_MEMBER(heathrow_device::cb2_w) +{ + m_via1->write_cb2(state); +} + +u16 heathrow_device::mac_via_r(offs_t offset) +{ + u16 data; + + offset >>= 8; + offset &= 0x0f; + + if (!machine().side_effects_disabled()) + via_sync(); + + data = m_via1->read(offset); + + return (data & 0xff) | (data << 8); +} + +void heathrow_device::mac_via_w(offs_t offset, u16 data, u16 mem_mask) +{ + offset >>= 8; + offset &= 0x0f; + + via_sync(); + + if (ACCESSING_BITS_0_7) + m_via1->write(offset, data & 0xff); + if (ACCESSING_BITS_8_15) + m_via1->write(offset, (data >> 8) & 0xff); +} + +void heathrow_device::via_sync() +{ + // The via runs at 783.36KHz while the main cpu runs at 15MHz or + // more, so we need to sync the access with the via clock. Plus + // the whole access takes half a (via) cycle and ends when synced + // with the main cpu again. + + // Get the main cpu time + u64 cycle = m_maincpu->total_cycles(); + + // Get the number of the cycle the via is in at that time + u64 via_cycle = cycle * m_via1->clock() / m_maincpu->clock(); + + // The access is going to start at via_cycle+1 and end at + // via_cycle+1.5, compute what that means in maincpu cycles (the + // +1 rounds up, since the clocks are too different to ever be + // synced). + u64 main_cycle = (via_cycle * 2 + 3) * m_maincpu->clock() / (2 * m_via1->clock()) + 1; + + // Finally adjust the main cpu icount as needed. + m_maincpu->adjust_icount(-int(main_cycle - cycle)); +} + +u16 heathrow_device::swim_r(offs_t offset, u16 mem_mask) +{ + if (!machine().side_effects_disabled()) + { + m_maincpu->adjust_icount(-5); + } + + u16 result = m_fdc->read((offset >> 8) & 0xf); + return result << 8; +} +void heathrow_device::swim_w(offs_t offset, u16 data, u16 mem_mask) +{ + if (ACCESSING_BITS_0_7) + m_fdc->write((offset >> 8) & 0xf, data & 0xff); + else + m_fdc->write((offset >> 8) & 0xf, data >> 8); +} + +void heathrow_device::phases_w(u8 phases) +{ + if (m_cur_floppy) + m_cur_floppy->seek_phase_w(phases); +} + +void heathrow_device::devsel_w(u8 devsel) +{ + if (devsel == 1) + m_cur_floppy = m_floppy[0]->get_device(); + else if (devsel == 2) + m_cur_floppy = m_floppy[1]->get_device(); + else + m_cur_floppy = nullptr; + + m_fdc->set_floppy(m_cur_floppy); + if (m_cur_floppy) + m_cur_floppy->ss_w(m_hdsel); +} + +u32 heathrow_device::macio_r(offs_t offset) +{ +// printf("macio_r: offset %x (%x)\n", offset, offset*4); + return 0; +} + +void heathrow_device::macio_w(offs_t offset, u32 data, u32 mem_mask) +{ +// printf("macio_w: offset %x (%x) data %08x mask %08x\n", offset, offset*4, data, mem_mask); +} + +u8 heathrow_device::fdc_r(offs_t offset) +{ + return m_fdc->read(offset >> 9); +} + +void heathrow_device::fdc_w(offs_t offset, u8 data) +{ + m_fdc->write(offset >> 9, data); +} + +u8 heathrow_device::nvram_r(offs_t offset) +{ + return m_nvram[offset >> 2]; +} + +void heathrow_device::nvram_w(offs_t offset, u8 data) +{ + m_nvram[offset >> 2] = data; +} + +u16 heathrow_device::scc_r(offs_t offset) +{ + u16 result = m_scc->dc_ab_r(offset); + return (result << 8) | result; +} + +void heathrow_device::scc_w(offs_t offset, u16 data) +{ + m_scc->dc_ab_w(offset, data >> 8); +} + +u8 heathrow_device::scc_macrisc_r(offs_t offset) +{ + switch ((offset >> 4) & 0xf) + { + case 0: + return m_scc->cb_r(0); + + case 1: + return m_scc->db_r(0); + + case 2: + return m_scc->ca_r(0); + + case 3: + return m_scc->da_r(0); + } + return 0; +} + +void heathrow_device::scc_macrisc_w(offs_t offset, u8 data) +{ + switch ((offset >> 4) & 0xf) + { + case 0: + return m_scc->cb_w(0, data); + + case 1: + return m_scc->db_w(0, data); + + case 2: + return m_scc->ca_w(0, data); + + case 3: + return m_scc->da_w(0, data); + } +} + diff --git a/src/mame/apple/heathrow.h b/src/mame/apple/heathrow.h new file mode 100644 index 00000000000..27128233e20 --- /dev/null +++ b/src/mame/apple/heathrow.h @@ -0,0 +1,117 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont + +#ifndef MAME_APPLE_HEATHROW_H +#define MAME_APPLE_HEATHROW_H + +#pragma once + +#include "machine/pci.h" +#include "machine/6522via.h" +#include "machine/applefdintf.h" +#include "machine/swim3.h" +#include "machine/z80scc.h" +#include "speaker.h" +#include "sound/awacs.h" + +// ======================> heathrow_device + +class heathrow_device : public pci_device +{ +public: + // construction/destruction + heathrow_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + heathrow_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + // interface routines + auto pb4_callback() { return write_pb4.bind(); } + auto pb5_callback() { return write_pb5.bind(); } + auto cb2_callback() { return write_cb2.bind(); } + auto pb3_callback() { return read_pb3.bind(); } + + void map(address_map &map); + + template void set_maincpu_tag(T &&... args) { m_maincpu.set_tag(std::forward(args)...); } + + DECLARE_WRITE_LINE_MEMBER(cb1_w); + DECLARE_WRITE_LINE_MEMBER(cb2_w); + DECLARE_WRITE_LINE_MEMBER(scc_irq_w); + +protected: + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + virtual void device_add_mconfig(machine_config &config) override; + + virtual void config_map(address_map &map) override; + + void common_init(); + +private: + emu_timer *m_6015_timer; + devcb_write_line write_pb4, write_pb5, write_cb2; + devcb_read_line read_pb3; + + required_device m_maincpu; + required_device m_via1; + required_device m_fdc; + required_device_array m_floppy; + required_device m_awacs; + required_device m_scc; + + floppy_image_device *m_cur_floppy = nullptr; + int m_hdsel; + + u8 m_nvram[0x20000/4]; + + u16 mac_via_r(offs_t offset); + void mac_via_w(offs_t offset, u16 data, u16 mem_mask); + + u8 via_in_a(); + u8 via_in_b(); + void via_out_a(u8 data); + void via_out_b(u8 data); + void via_sync(); + void field_interrupts(); + DECLARE_WRITE_LINE_MEMBER(via_out_cb2); + DECLARE_WRITE_LINE_MEMBER(via1_irq); + DECLARE_WRITE_LINE_MEMBER(via2_irq); + DECLARE_WRITE_LINE_MEMBER(asc_irq); + TIMER_CALLBACK_MEMBER(mac_6015_tick); + + void phases_w(u8 phases); + void devsel_w(u8 devsel); + uint16_t swim_r(offs_t offset, u16 mem_mask); + void swim_w(offs_t offset, u16 data, u16 mem_mask); + + u32 macio_r(offs_t offset); + void macio_w(offs_t offset, u32 data, u32 mem_mask); + + u8 fdc_r(offs_t offset); + void fdc_w(offs_t offset, u8 data); + + u8 nvram_r(offs_t offset); + void nvram_w(offs_t offset, u8 data); + + u16 scc_r(offs_t offset); + void scc_w(offs_t offset, u16 data); + u8 scc_macrisc_r(offs_t offset); + void scc_macrisc_w(offs_t offset, u8 data); +}; + +class paddington_device : public heathrow_device +{ +public: + // construction/destruction + paddington_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + +protected: + // device-level overrides + virtual void device_start() override; +}; + +// device type definition +DECLARE_DEVICE_TYPE(HEATHROW, heathrow_device) +DECLARE_DEVICE_TYPE(PADDINGTON, paddington_device) + +#endif // MAME_APPLE_HEATHROW_H diff --git a/src/mame/apple/imacg3.cpp b/src/mame/apple/imacg3.cpp new file mode 100644 index 00000000000..6cc7ae7e6a4 --- /dev/null +++ b/src/mame/apple/imacg3.cpp @@ -0,0 +1,101 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont +/**************************************************************************** + + imacg3.cpp + iMac G3 (original hardware) + Preliminary driver by R. Belmont + + This is a "New World" PCI-based machine. + + CPU: PowerPC 750 "G3" @ 233 MHz + Memory controller/PCI bridge: Motorola MPC106 "Grackle" + Video: ATI Rage IIc w/2MB VRAM, ATI Rage Pro Turbo w/6MB VRAM on revised model + USB: OPTi 82C861 PCI/USB controller + I/O: Paddington PCI I/O ASIC (see heathrow.cpp for details) + +****************************************************************************/ + +#include "emu.h" +#include "cpu/powerpc/ppc.h" +#include "machine/pci.h" +#include "machine/pci-ide.h" +#include "machine/mpc106.h" +#include "cuda.h" +#include "heathrow.h" + +class imac_state : public driver_device +{ +public: + void imac(machine_config &config); + + imac_state(const machine_config &mconfig, device_type type, const char *tag); + + required_device m_maincpu; + required_device m_cuda; + +private: + void imac_map(address_map &map); + + virtual void machine_start() override; + virtual void machine_reset() override; + + WRITE_LINE_MEMBER(cuda_reset_w) + { + m_maincpu->set_input_line(INPUT_LINE_HALT, state); + m_maincpu->set_input_line(INPUT_LINE_RESET, state); + } +}; + +imac_state::imac_state(const machine_config &mconfig, device_type type, const char *tag) : + driver_device(mconfig, type, tag), + m_maincpu(*this, "maincpu"), + m_cuda(*this, "cuda") +{ +} + +void imac_state::machine_start() +{ +} + +void imac_state::machine_reset() +{ +} + +void imac_state::imac_map(address_map &map) +{ + map.unmap_value_high(); +} + +void imac_state::imac(machine_config &config) +{ + PPC604(config, m_maincpu, 66000000); // actually PPC750 + m_maincpu->set_addrmap(AS_PROGRAM, &imac_state::imac_map); + + PCI_ROOT(config, "pci", 0); + MPC106(config, "pci:00.0", 0, mpc106_host_device::MAP_TYPE_B, "maincpu", "bootrom", 32 * 1024 * 1024); + + paddington_device &paddington(PADDINGTON(config, "pci:10.0", 0)); + paddington.set_maincpu_tag("maincpu"); + + CUDA(config, m_cuda, CUDA_341S0060); + m_cuda->reset_callback().set(FUNC(imac_state::cuda_reset_w)); + m_cuda->via_clock_callback().set(paddington, FUNC(paddington_device::cb1_w)); + m_cuda->via_data_callback().set(paddington, FUNC(paddington_device::cb2_w)); + config.set_perfect_quantum(m_maincpu); + + paddington.pb3_callback().set(m_cuda, FUNC(cuda_device::get_treq)); + paddington.pb4_callback().set(m_cuda, FUNC(cuda_device::set_byteack)); + paddington.pb5_callback().set(m_cuda, FUNC(cuda_device::set_tip)); + paddington.cb2_callback().set(m_cuda, FUNC(cuda_device::set_via_data)); +} + +ROM_START(imac) + ROM_REGION(0x100000, "bootrom", ROMREGION_64BIT | ROMREGION_BE) + ROM_LOAD( "imacboot.u3", 0x000000, 0x100000, CRC(80d3174b) SHA1(e7a0c71822ec1e08435099af87b38bc82d315ed5) ) +ROM_END + +static INPUT_PORTS_START(imac) +INPUT_PORTS_END + +COMP(1998, imac, 0, 0, imac, imac, imac_state, empty_init, "Apple Computer", "iMac (Bondi blue)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND) diff --git a/src/mame/apple/powermacg3.cpp b/src/mame/apple/powermacg3.cpp new file mode 100644 index 00000000000..4d782da2bde --- /dev/null +++ b/src/mame/apple/powermacg3.cpp @@ -0,0 +1,103 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont +/**************************************************************************** + + powermacg3.cpp + PowerMac G3 (original beige hardware) + Preliminary driver by R. Belmont + + The last desktop Old World Mac, with hardware very similar to the first + New World machines. + + CPU: PowerPC 750 "G3" @ 233 MHz + Memory controller/PCI bridge: Motorola MPC106 "Grackle" + Video: ATI Rage II+, ATI Rage Pro on rev. B, ATI Rage Pro Turbo on rev. C + I/O: Heathrow PCI I/O ASIC (see heathrow.cpp for details) + +****************************************************************************/ + +#include "emu.h" +#include "cpu/powerpc/ppc.h" +#include "machine/pci.h" +#include "machine/pci-ide.h" +#include "machine/mpc106.h" +#include "heathrow.h" + +class pwrmacg3_state : public driver_device +{ +public: + void pwrmacg3(machine_config &config); + + pwrmacg3_state(const machine_config &mconfig, device_type type, const char *tag); + + required_device m_maincpu; + +private: + void pwrmacg3_map(address_map &map); + + virtual void machine_start() override; + virtual void machine_reset() override; +}; + +pwrmacg3_state::pwrmacg3_state(const machine_config &mconfig, device_type type, const char *tag) : + driver_device(mconfig, type, tag), + m_maincpu(*this, "maincpu") +{ +} + +void pwrmacg3_state::machine_start() +{ +} + +void pwrmacg3_state::machine_reset() +{ +} + +void pwrmacg3_state::pwrmacg3_map(address_map &map) +{ + map.unmap_value_high(); +} + +void pwrmacg3_state::pwrmacg3(machine_config &config) +{ + PPC604(config, m_maincpu, 66000000); // actually PPC750 + m_maincpu->set_addrmap(AS_PROGRAM, &pwrmacg3_state::pwrmacg3_map); + + PCI_ROOT(config, "pci", 0); + MPC106(config, "pci:00.0", 0, mpc106_host_device::MAP_TYPE_B, "maincpu", "bootrom", 32 * 1024 * 1024); + + heathrow_device &heathrow(HEATHROW(config, "pci:10.0", 0)); + heathrow.set_maincpu_tag("maincpu"); +} + +/* + Config register for Gossamer beige G3 and all-in-one + bit 15: 1 = SWIM3, 0 = PC style FDC + bit 14: 1 = slow ROM, 0 = burstable ROM + bit 12 = PCI slot C card present + bit 10 = PCI slot B card present + bit 8 = PCI slot A card present + bits 7-5 = bus to CPU clock ratio (1 for 2:1) + bit 4: 0 = all-in-one "Molar Mac", 1 = Desktop beige G3 + bits 3-1: bus speed (0=75 MHz, 1=70, 2=78.75, 3=invalid, 4=75, 5=60, 6=66.82, 7=83) + bit 0: must be 1 (burn-in diagnostics?) + + desktop = 0b1001010100111101; + AIO = 0b1001010100101101; +*/ +ROM_START(pwrmacg3) + ROM_REGION(0x1000000, "bootrom", ROMREGION_64BIT | ROMREGION_BE | ROMREGION_ERASEFF) + ROM_LOAD( "pmacg3_79d68d63.bin", 0xc00000, 0x400000, CRC(74a3badf) SHA1(e7fc183f62addc6499350c727252d3348184955e) ) + + // The Gossamer machine config register is at 0xFF000000, which is in the MPC106's ROM space. + // So we're hacking it like this. Hardware is assumed to operate similarly. + ROM_FILL(0, 1, 0b10010101) + ROM_FILL(1, 1, 0b00111101) + ROM_FILL(2, 1, 0b10010101) + ROM_FILL(3, 1, 0b00111101) +ROM_END + +static INPUT_PORTS_START(pwrmacg3) +INPUT_PORTS_END + +COMP(1997, pwrmacg3, 0, 0, pwrmacg3, pwrmacg3, pwrmacg3_state, empty_init, "Apple Computer", "Power Macintosh G3", MACHINE_NOT_WORKING | MACHINE_NO_SOUND) diff --git a/src/mame/mame.lst b/src/mame/mame.lst index 812255938f0..0c89dbd42c9 100644 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -802,6 +802,9 @@ apple2gsmt // 1991 "Mark Twain" prototype @source:apple/apple3.cpp apple3 // May 1980 Apple /// +@source:apple/imacg3.cpp +imac // August 15, 1998 Apple iMac (Bondi blue) + @source:apple/iphone2g.cpp iphone2g // (c) 2007 Apple @@ -887,6 +890,9 @@ emate mp2000 mp2100 +@source:apple/powermacg3.cpp +pwrmacg3 // November 10, 1997 Apple Power Macintosh G3 (beige) + @source:apple/superga2.cpp kuzmich