mirror of
https://github.com/holub/mame
synced 2025-04-22 08:22:15 +03:00
machine/mpc106.cpp: properly endian-swap PPC/PCI transactions, support LE PPC, use logmacro. [R. Belmont]
apple/bandit.cpp: properly endian-swap PPC/PCI transactions, use logmacro. [R. Belmont] apple/heathrow.cpp: interrupt controller filled out, audio CODEC interface defined, added audio DMA channels. [R. Belmont] apple/dbdma.cpp: New device, a single Descriptor Based DMA channel. [R. Belmont] apple/awacs_macrisc.cpp: New device, the AWACS and Screamer CODECs in their MacRISC compatible form. [R. Belmont] apple/burgundy.cpp: New device, MacRISC compatible CODEC used in the iMac G3 and "Blue & White" G3. apple/imacg3.cpp: Boot chime now plays. [R. Belmont] apple/powermacg3.cpp: Boot chime now plays. [R. Belmont]
This commit is contained in:
parent
47202637e6
commit
59baa6640b
@ -22,6 +22,8 @@ enum
|
||||
AS_PCI_IO = 2
|
||||
};
|
||||
|
||||
constexpr u32 PICR1_LE_MODE = 0x00000020; // Host CPU is little-endian if set, big-endian if clear
|
||||
|
||||
DEFINE_DEVICE_TYPE(MPC106, mpc106_host_device, "mpc106", "Motorola MPC106 PCI Bridge/Memory Controller")
|
||||
|
||||
void mpc106_host_device::config_map(address_map &map)
|
||||
@ -32,6 +34,7 @@ void mpc106_host_device::config_map(address_map &map)
|
||||
map(0x80, 0x8f).rw(FUNC(mpc106_host_device::memory_start_r), FUNC(mpc106_host_device::memory_start_w));
|
||||
map(0x90, 0x9f).rw(FUNC(mpc106_host_device::memory_end_r), FUNC(mpc106_host_device::memory_end_w));
|
||||
map(0xa0, 0xa0).rw(FUNC(mpc106_host_device::memory_enable_r), FUNC(mpc106_host_device::memory_enable_w));
|
||||
map(0xa8, 0xab).rw(FUNC(mpc106_host_device::picr1_r), FUNC(mpc106_host_device::picr1_w));
|
||||
}
|
||||
|
||||
mpc106_host_device::mpc106_host_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
|
||||
@ -42,6 +45,7 @@ mpc106_host_device::mpc106_host_device(const machine_config &mconfig, const char
|
||||
{
|
||||
set_ids_host(0x10570002, 0x40, 0x000006);
|
||||
m_memory_bank_enable = 0;
|
||||
m_picr1 = 0;
|
||||
}
|
||||
|
||||
void mpc106_host_device::set_ram_info(u8 *ram_ptr, int ram_size)
|
||||
@ -108,7 +112,14 @@ void mpc106_host_device::device_start()
|
||||
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<mpc106_host_device *>(this), &mpc106_host_device::access_map);
|
||||
if (m_picr1 & PICR1_LE_MODE)
|
||||
{
|
||||
m_cpu_space->install_device(0xfec00000, 0xfeefffff, *static_cast<mpc106_host_device *>(this), &mpc106_host_device::access_map_le);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_cpu_space->install_device(0xfec00000, 0xfeefffff, *static_cast<mpc106_host_device *>(this), &mpc106_host_device::access_map_be);
|
||||
}
|
||||
}
|
||||
|
||||
save_item(NAME(m_pwrconfig1));
|
||||
@ -116,6 +127,7 @@ void mpc106_host_device::device_start()
|
||||
save_item(NAME(m_memory_starts));
|
||||
save_item(NAME(m_memory_ends));
|
||||
save_item(NAME(m_memory_bank_enable));
|
||||
save_item(NAME(m_picr1));
|
||||
}
|
||||
|
||||
device_memory_interface::space_config_vector mpc106_host_device::memory_space_config() const
|
||||
@ -136,7 +148,13 @@ void mpc106_host_device::device_reset()
|
||||
pci_host_device::device_reset();
|
||||
}
|
||||
|
||||
void mpc106_host_device::access_map(address_map &map)
|
||||
void mpc106_host_device::access_map_le(address_map &map)
|
||||
{
|
||||
map(0x00000000, 0x001fffff).rw(FUNC(mpc106_host_device::config_address_r), FUNC(mpc106_host_device::config_address_w));
|
||||
map(0x00200000, 0x002fffff).rw(FUNC(mpc106_host_device::config_data_r), FUNC(mpc106_host_device::config_data_w));
|
||||
}
|
||||
|
||||
void mpc106_host_device::access_map_be(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));
|
||||
@ -149,32 +167,43 @@ u32 mpc106_host_device::be_config_address_r()
|
||||
|
||||
void mpc106_host_device::be_config_address_w(offs_t offset, u32 data, u32 mem_mask)
|
||||
{
|
||||
const u32 tempdata = swapendian_int32(data);
|
||||
pci_host_device::config_address_w(offset, tempdata, mem_mask);
|
||||
pci_host_device::config_address_w(offset, swapendian_int32(data), swapendian_int32(mem_mask));
|
||||
}
|
||||
|
||||
u32 mpc106_host_device::be_config_data_r(offs_t offset, u32 mem_mask)
|
||||
{
|
||||
return swapendian_int32(pci_host_device::config_data_r(offset, mem_mask));
|
||||
return swapendian_int32(pci_host_device::config_data_r(offset, swapendian_int32(mem_mask)));
|
||||
}
|
||||
|
||||
void mpc106_host_device::be_config_data_w(offs_t offset, u32 data, u32 mem_mask)
|
||||
{
|
||||
const u32 tempdata = swapendian_int32(data);
|
||||
pci_host_device::config_data_w(offset, tempdata, mem_mask);
|
||||
pci_host_device::config_data_w(offset, swapendian_int32(data), swapendian_int32(mem_mask));
|
||||
}
|
||||
|
||||
template <u32 Base>
|
||||
u32 mpc106_host_device::cpu_memory_r(offs_t offset, u32 mem_mask)
|
||||
{
|
||||
const u32 result = m_cpu_space->read_dword(Base + (offset * 4), mem_mask);
|
||||
return result;
|
||||
if (m_picr1 & PICR1_LE_MODE)
|
||||
{
|
||||
return m_cpu_space->read_dword(Base + (offset * 4), mem_mask);
|
||||
}
|
||||
else
|
||||
{
|
||||
return swapendian_int32(m_cpu_space->read_dword(Base + (offset * 4), swapendian_int32(mem_mask)));
|
||||
}
|
||||
}
|
||||
|
||||
template <u32 Base>
|
||||
void mpc106_host_device::cpu_memory_w(offs_t offset, u32 data, u32 mem_mask)
|
||||
{
|
||||
m_cpu_space->write_dword(Base + (offset * 4), data, mem_mask);
|
||||
if (m_picr1 & PICR1_LE_MODE)
|
||||
{
|
||||
m_cpu_space->write_dword(Base + (offset * 4), data, mem_mask);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_cpu_space->write_dword(Base + (offset * 4), swapendian_int32(data), swapendian_int32(mem_mask));
|
||||
}
|
||||
}
|
||||
|
||||
template u32 mpc106_host_device::cpu_memory_r<0>(offs_t offset, u32 mem_mask);
|
||||
@ -186,14 +215,27 @@ template void mpc106_host_device::cpu_memory_w<0xff800000>(offs_t offset, u32 da
|
||||
template <u32 Base>
|
||||
u32 mpc106_host_device::pci_memory_r(offs_t offset, u32 mem_mask)
|
||||
{
|
||||
const u32 result = this->space(AS_PCI_MEM).read_dword(Base + (offset * 4), mem_mask);
|
||||
return result;
|
||||
if (m_picr1 & PICR1_LE_MODE)
|
||||
{
|
||||
return this->space(AS_PCI_MEM).read_dword(Base + (offset * 4), mem_mask);
|
||||
}
|
||||
else
|
||||
{
|
||||
return swapendian_int32(this->space(AS_PCI_MEM).read_dword(Base + (offset * 4), swapendian_int32(mem_mask)));
|
||||
}
|
||||
}
|
||||
|
||||
template <u32 Base>
|
||||
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);
|
||||
if (m_picr1 & PICR1_LE_MODE)
|
||||
{
|
||||
this->space(AS_PCI_MEM).write_dword(Base + (offset * 4), data, mem_mask);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->space(AS_PCI_MEM).write_dword(Base + (offset * 4), swapendian_int32(data), swapendian_int32((mem_mask)));
|
||||
}
|
||||
}
|
||||
|
||||
template u32 mpc106_host_device::pci_memory_r<0>(offs_t offset, u32 mem_mask);
|
||||
@ -205,14 +247,27 @@ template void mpc106_host_device::pci_memory_w<0x80000000>(offs_t offset, u32 da
|
||||
template <u32 Base>
|
||||
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;
|
||||
if (m_picr1 & PICR1_LE_MODE)
|
||||
{
|
||||
return this->space(AS_PCI_IO).read_dword(Base + (offset * 4), mem_mask);
|
||||
}
|
||||
else
|
||||
{
|
||||
return swapendian_int32(this->space(AS_PCI_IO).read_dword(Base + (offset * 4), swapendian_int32(mem_mask)));
|
||||
}
|
||||
}
|
||||
|
||||
template <u32 Base>
|
||||
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);
|
||||
if (m_picr1 & PICR1_LE_MODE)
|
||||
{
|
||||
this->space(AS_PCI_IO).write_dword(Base + (offset * 4), data, mem_mask);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->space(AS_PCI_IO).write_dword(Base + (offset * 4), swapendian_int32(data), swapendian_int32((mem_mask)));
|
||||
}
|
||||
}
|
||||
|
||||
template u32 mpc106_host_device::pci_io_r<0>(offs_t offset, u32 mem_mask);
|
||||
@ -319,3 +374,13 @@ void mpc106_host_device::memory_enable_w(offs_t offset, u8 data)
|
||||
end2 >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
u32 mpc106_host_device::picr1_r()
|
||||
{
|
||||
return m_picr1;
|
||||
}
|
||||
|
||||
void mpc106_host_device::picr1_w(u32 data)
|
||||
{
|
||||
m_picr1 = data;
|
||||
}
|
||||
|
@ -51,7 +51,8 @@ protected:
|
||||
virtual space_config_vector memory_space_config() const override;
|
||||
|
||||
private:
|
||||
void access_map(address_map &map);
|
||||
void access_map_le(address_map &map);
|
||||
void access_map_be(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);
|
||||
@ -73,6 +74,8 @@ private:
|
||||
void memory_end_w(offs_t offset, u32 data, u32 mem_mask);
|
||||
u8 memory_enable_r();
|
||||
void memory_enable_w(offs_t offset, u8 data);
|
||||
u32 picr1_r();
|
||||
void picr1_w(u32 data);
|
||||
|
||||
address_space_config m_mem_config, m_io_config;
|
||||
const char *m_rom_tag;
|
||||
@ -87,6 +90,7 @@ private:
|
||||
u8 m_pwrconfig2;
|
||||
u32 m_memory_starts[4];
|
||||
u32 m_memory_ends[4];
|
||||
u32 m_picr1;
|
||||
u8 m_memory_bank_enable;
|
||||
};
|
||||
|
||||
|
210
src/mame/apple/awacs_macrisc.cpp
Normal file
210
src/mame/apple/awacs_macrisc.cpp
Normal file
@ -0,0 +1,210 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:R. Belmont
|
||||
/***************************************************************************
|
||||
|
||||
awacs_macrisc.cpp
|
||||
|
||||
AWACS/Screamer 16-bit audio I/O for "MacRisc" architecture Macs (PCI-based)
|
||||
|
||||
AWACS and Screamer are audio CODECs that comply with a specification.
|
||||
Data transfer to and from them is done in terms of serial frames.
|
||||
|
||||
Screamer is back-compatible with AWACS but supports more mixer inputs and
|
||||
better power management.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "awacs_macrisc.h"
|
||||
|
||||
#define LOG_GENERAL (1U << 0)
|
||||
#define LOG_REGISTERS (1U << 0)
|
||||
|
||||
#define VERBOSE (0)
|
||||
#include "logmacro.h"
|
||||
|
||||
constexpr u16 REGISTER_1_MUTE = 0x100;
|
||||
|
||||
// device type definition
|
||||
DEFINE_DEVICE_TYPE(AWACS_MACRISC, awacs_macrisc_device, "awacsmr", "AWACS MacRisc audio I/O")
|
||||
DEFINE_DEVICE_TYPE(SCREAMER, screamer_device, "screamer", "Screamer audio I/O")
|
||||
|
||||
//**************************************************************************
|
||||
// LIVE DEVICE
|
||||
//**************************************************************************
|
||||
|
||||
//-------------------------------------------------
|
||||
// awacs_macrisc_device - constructor
|
||||
//-------------------------------------------------
|
||||
|
||||
awacs_macrisc_device::awacs_macrisc_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_sound_interface(mconfig, *this)
|
||||
, m_output_cb(*this)
|
||||
, m_input_cb(*this)
|
||||
, m_stream(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
awacs_macrisc_device::awacs_macrisc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: awacs_macrisc_device(mconfig, AWACS_MACRISC, tag, owner, clock)
|
||||
{
|
||||
}
|
||||
|
||||
screamer_device::screamer_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: awacs_macrisc_device(mconfig, SCREAMER, tag, owner, clock)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
|
||||
void awacs_macrisc_device::device_start()
|
||||
{
|
||||
// create the stream
|
||||
m_stream = stream_alloc(0, 2, clock()/1024, STREAM_SYNCHRONOUS);
|
||||
|
||||
m_output_cb.resolve_safe(0);
|
||||
m_input_cb.resolve_safe();
|
||||
|
||||
save_item(NAME(m_phase));
|
||||
save_item(NAME(m_active));
|
||||
save_item(NAME(m_registers));
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_reset - device-specific reset
|
||||
//-------------------------------------------------
|
||||
|
||||
void awacs_macrisc_device::device_reset()
|
||||
{
|
||||
m_phase = 0;
|
||||
m_active = ACTIVE_OUT; // AWACS is always running, Screamer has a real enable/disable bit
|
||||
m_registers[1] = REGISTER_1_MUTE;
|
||||
m_stream->set_sample_rate(clock() / 1024);
|
||||
}
|
||||
|
||||
void screamer_device::device_reset()
|
||||
{
|
||||
awacs_macrisc_device::device_reset();
|
||||
m_active = 0;
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// sound_stream_update - handle update requests for
|
||||
// our sound stream
|
||||
//-------------------------------------------------
|
||||
|
||||
void awacs_macrisc_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
|
||||
{
|
||||
// if we're active and not muted
|
||||
if ((m_active & ACTIVE_OUT) && !(m_registers[1] & REGISTER_1_MUTE))
|
||||
{
|
||||
const s16 atten_L = 0xf - (m_registers[2] >> 6) & 0xf;
|
||||
const s16 atten_R = 0xf - m_registers[2] & 0xf;
|
||||
|
||||
const u32 data = swapendian_int32(m_output_cb(m_phase));
|
||||
const s16 l_raw = (s16)(data >> 16);
|
||||
const s16 r_raw = (s16)(data & 0xffff);
|
||||
|
||||
const s32 left = ((s32)l_raw * atten_L) >> 4;
|
||||
const s32 right = ((s32)r_raw * atten_R) >> 4;
|
||||
outputs[0].put_int(0, left, 32768);
|
||||
outputs[1].put_int(0, right, 32768);
|
||||
}
|
||||
else
|
||||
{
|
||||
outputs[0].put_int(0, 0, 32768);
|
||||
outputs[1].put_int(0, 0, 32768);
|
||||
}
|
||||
|
||||
m_phase = (m_phase + 1) & 0xfff;
|
||||
}
|
||||
|
||||
uint32_t awacs_macrisc_device::read_macrisc(offs_t offset)
|
||||
{
|
||||
LOGMASKED(LOG_REGISTERS, "read AWACS @ %x\n", offset);
|
||||
switch (offset)
|
||||
{
|
||||
case 0: // Audio Control
|
||||
return 0;
|
||||
|
||||
case 4: // Audio CODEC Control
|
||||
return 0;
|
||||
|
||||
case 8: // Audio CODEC Status
|
||||
return 0x314000; // Screamer info
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void awacs_macrisc_device::write_macrisc(offs_t offset, uint32_t data)
|
||||
{
|
||||
static const int rates[8] = { 512, 768, 1024, 1280, 1536, 2048, 2560, 3072 };
|
||||
|
||||
LOGMASKED(LOG_REGISTERS, "%s: %08x @ %x\n", tag(), data, offset*4);
|
||||
switch (offset)
|
||||
{
|
||||
case 0: // Audio Control
|
||||
m_stream->set_sample_rate(clock() / rates[(data >> 8) & 7]);
|
||||
LOGMASKED(LOG_GENERAL, "%s: sample rate to %d Hz\n", tag(), clock() / rates[(data >> 8) & 7]);
|
||||
break;
|
||||
|
||||
case 4: // Audio CODEC Control
|
||||
{
|
||||
int subframe = (data >> 22) & 0x3;
|
||||
int codec_addr = (data >> 12) & 0xfff;
|
||||
int codec_data = (data & 0xfff);
|
||||
|
||||
LOGMASKED(LOG_REGISTERS, "%s: CODEC control: %x to addr %x (subframe %d)\n", tag(), codec_data, codec_addr, subframe);
|
||||
|
||||
m_registers[codec_addr] = codec_data;
|
||||
}
|
||||
break;
|
||||
|
||||
case 8: // Audio CODEC Status
|
||||
break;
|
||||
|
||||
case 12: // Byte swap
|
||||
printf("CODEC byte swap: %08x\n", data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Screamer
|
||||
uint32_t screamer_device::read_macrisc(offs_t offset)
|
||||
{
|
||||
switch (offset)
|
||||
{
|
||||
case 0: // Audio Control
|
||||
return 0;
|
||||
|
||||
case 4: // Audio CODEC Control
|
||||
return 0;
|
||||
|
||||
case 8: // Audio CODEC Status
|
||||
return swapendian_int32((0x40 << 8) | // indicate CODEC is present
|
||||
(1 << 16) | // manufacturer is Crystal Semiconductor
|
||||
(3 << 20)); // CODEC version 3 (Screamer)
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void screamer_device::write_macrisc(offs_t offset, uint32_t data)
|
||||
{
|
||||
awacs_macrisc_device::write_macrisc(offset, data);
|
||||
|
||||
// if IDLE bit is off, we're active
|
||||
if (!BIT(m_registers[6], 1))
|
||||
{
|
||||
m_active |= ACTIVE_OUT;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_active &= ~ACTIVE_OUT;
|
||||
}
|
||||
LOGMASKED(LOG_GENERAL, "%s: Playback %s reg 6 %x)\n", tag(), !BIT(m_registers[6], 1) ? "on" : "off", m_registers[6]);
|
||||
}
|
76
src/mame/apple/awacs_macrisc.h
Normal file
76
src/mame/apple/awacs_macrisc.h
Normal file
@ -0,0 +1,76 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:R. Belmont
|
||||
/***************************************************************************
|
||||
|
||||
awacs_macrisc.h
|
||||
|
||||
AWACS/Screamer 16-bit audio I/O for "MacRisc" architecture Macs (PCI-based)
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MAME_APPLE_AWACS_MACRISC_H
|
||||
#define MAME_APPLE_AWACS_MACRISC_H
|
||||
|
||||
#pragma once
|
||||
|
||||
//**************************************************************************
|
||||
// TYPE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
// ======================> awacs_macrisc_device
|
||||
|
||||
class awacs_macrisc_device : public device_t, public device_sound_interface
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
awacs_macrisc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
auto dma_output() { return m_output_cb.bind(); }
|
||||
auto dma_input() { return m_input_cb.bind(); }
|
||||
|
||||
virtual u32 read_macrisc(offs_t offset);
|
||||
virtual void write_macrisc(offs_t offset, u32 data);
|
||||
|
||||
protected:
|
||||
awacs_macrisc_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
|
||||
|
||||
enum {
|
||||
ACTIVE_OUT = 0x01,
|
||||
ACTIVE_IN = 0x02
|
||||
};
|
||||
|
||||
static const u8 divider[4];
|
||||
|
||||
// device-level overrides
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override;
|
||||
|
||||
devcb_read32 m_output_cb;
|
||||
devcb_write32 m_input_cb;
|
||||
|
||||
sound_stream *m_stream;
|
||||
|
||||
u32 m_registers[16];
|
||||
u8 m_active;
|
||||
u16 m_phase;
|
||||
};
|
||||
|
||||
class screamer_device : public awacs_macrisc_device
|
||||
{
|
||||
public:
|
||||
screamer_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
|
||||
|
||||
virtual u32 read_macrisc(offs_t offset) override;
|
||||
virtual void write_macrisc(offs_t offset, u32 data) override;
|
||||
|
||||
protected:
|
||||
virtual void device_reset() override;
|
||||
};
|
||||
|
||||
// device type definition
|
||||
DECLARE_DEVICE_TYPE(AWACS_MACRISC, awacs_macrisc_device)
|
||||
DECLARE_DEVICE_TYPE(SCREAMER, screamer_device)
|
||||
|
||||
#endif // MAME_APPLE_AWACS_MACRISC_H
|
@ -156,14 +156,13 @@ void bandit_host_device::be_config_data_w(offs_t offset, u32 data, u32 mem_mask)
|
||||
template <u32 Base>
|
||||
u32 bandit_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;
|
||||
return swapendian_int32(this->space(AS_PCI_MEM).read_dword(Base + (offset * 4), swapendian_int32(mem_mask)));
|
||||
}
|
||||
|
||||
template <u32 Base>
|
||||
void bandit_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);
|
||||
this->space(AS_PCI_MEM).write_dword(Base + (offset * 4), swapendian_int32(data), swapendian_int32((mem_mask)));
|
||||
}
|
||||
|
||||
template u32 bandit_host_device::pci_memory_r<0x80000000>(offs_t offset, u32 mem_mask);
|
||||
@ -180,14 +179,13 @@ template void bandit_host_device::pci_memory_w<0xf7000000>(offs_t offset, u32 da
|
||||
template <u32 Base>
|
||||
u32 bandit_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;
|
||||
return swapendian_int32(this->space(AS_PCI_IO).read_dword(Base + (offset * 4), swapendian_int32(mem_mask)));
|
||||
}
|
||||
|
||||
template <u32 Base>
|
||||
void bandit_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);
|
||||
this->space(AS_PCI_IO).write_dword(Base + (offset * 4), swapendian_int32(data), swapendian_int32((mem_mask)));
|
||||
}
|
||||
|
||||
// map PCI memory and I/O space stuff here
|
||||
|
169
src/mame/apple/burgundy.cpp
Normal file
169
src/mame/apple/burgundy.cpp
Normal file
@ -0,0 +1,169 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:R. Belmont
|
||||
/***************************************************************************
|
||||
|
||||
burgundy.cpp
|
||||
|
||||
"Burgundy" stereo 16-bit audio CODEC (iMac, Blue & White G3)
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "burgundy.h"
|
||||
|
||||
#define LOG_GENERAL (1U << 0)
|
||||
#define LOG_REGISTERS (1U << 0)
|
||||
|
||||
#define VERBOSE (0)
|
||||
#include "logmacro.h"
|
||||
|
||||
// device type definition
|
||||
DEFINE_DEVICE_TYPE(BURGUNDY, burgundy_device, "burgundy", "Burgundy audio I/O")
|
||||
|
||||
constexpr u32 CODEC_BUSY = (1 << 23);
|
||||
constexpr u32 CODEC_PRESENT = (1 << 22);
|
||||
|
||||
//**************************************************************************
|
||||
// LIVE DEVICE
|
||||
//**************************************************************************
|
||||
|
||||
//-------------------------------------------------
|
||||
// burgundy_device - constructor
|
||||
//-------------------------------------------------
|
||||
|
||||
burgundy_device::burgundy_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: device_t(mconfig, BURGUNDY, tag, owner, clock)
|
||||
, device_sound_interface(mconfig, *this)
|
||||
, m_output_cb(*this)
|
||||
, m_input_cb(*this)
|
||||
, m_stream(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
|
||||
void burgundy_device::device_start()
|
||||
{
|
||||
// create the stream
|
||||
m_stream = stream_alloc(0, 2, clock() / 512, STREAM_SYNCHRONOUS);
|
||||
|
||||
m_output_cb.resolve_safe(0);
|
||||
m_input_cb.resolve_safe();
|
||||
|
||||
save_item(NAME(m_phase));
|
||||
save_item(NAME(m_active));
|
||||
save_item(NAME(m_registers));
|
||||
save_item(NAME(m_codec_status));
|
||||
save_item(NAME(m_counter));
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_reset - device-specific reset
|
||||
//-------------------------------------------------
|
||||
|
||||
void burgundy_device::device_reset()
|
||||
{
|
||||
m_phase = 0;
|
||||
m_codec_status = 0;
|
||||
m_counter = 0;
|
||||
m_stream->set_sample_rate(clock() / 512);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// sound_stream_update - handle update requests for
|
||||
// our sound stream
|
||||
//-------------------------------------------------
|
||||
|
||||
void burgundy_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
|
||||
{
|
||||
if (m_codec_status & CODEC_BUSY)
|
||||
{
|
||||
m_codec_status &= ~CODEC_BUSY; // clear busy
|
||||
m_counter++;
|
||||
m_counter &= 3;
|
||||
}
|
||||
|
||||
if (m_active & ACTIVE_OUT)
|
||||
{
|
||||
const u32 data = swapendian_int32(m_output_cb(m_phase));
|
||||
const s16 left = data >> 16;
|
||||
const s16 right = data;
|
||||
outputs[0].put_int(0, left, 32768);
|
||||
outputs[1].put_int(0, right, 32768);
|
||||
}
|
||||
else
|
||||
{
|
||||
outputs[0].put_int(0, 0, 32768);
|
||||
outputs[1].put_int(0, 0, 32768);
|
||||
}
|
||||
|
||||
m_phase = (m_phase + 1) & 0xfff;
|
||||
}
|
||||
|
||||
uint32_t burgundy_device::read_macrisc(offs_t offset)
|
||||
{
|
||||
switch (offset)
|
||||
{
|
||||
case 0: // Audio Control
|
||||
return 0;
|
||||
|
||||
case 4: // Audio CODEC Control
|
||||
return m_last_codec_control;
|
||||
|
||||
case 8: // Audio CODEC Status
|
||||
return m_codec_status;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void burgundy_device::write_macrisc(offs_t offset, uint32_t data)
|
||||
{
|
||||
switch (offset)
|
||||
{
|
||||
case 0: // Audio Control
|
||||
break;
|
||||
|
||||
case 4: // Audio CODEC Control
|
||||
m_last_codec_control = data;
|
||||
|
||||
m_reg_addr = (data >> 12) & 0xff;
|
||||
m_cur_byte = (data >> 8) & 3;
|
||||
m_last_byte = (data >> 10) & 3;
|
||||
|
||||
if (BIT(data, 21))
|
||||
{
|
||||
u32 reg_mask = 0xff << (m_cur_byte << 3);
|
||||
m_registers[m_reg_addr] &= ~reg_mask;
|
||||
m_registers[m_reg_addr] |= ((data & 0xff) << (m_cur_byte << 3));
|
||||
LOGMASKED(LOG_REGISTERS, "%s: reg %x is now %x\n", tag(), m_reg_addr, m_registers[m_reg_addr]);
|
||||
|
||||
if (m_reg_addr == 0x60)
|
||||
{
|
||||
if ((m_registers[0x60] & 6) != 0)
|
||||
{
|
||||
LOGMASKED(LOG_GENERAL, "%s: Playback enabled\n", tag());
|
||||
m_active |= ACTIVE_OUT;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGMASKED(LOG_GENERAL, "%s: Playback disabled\n", tag());
|
||||
m_active &= ~ACTIVE_OUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
u8 reg_data = (m_registers[m_reg_addr] >> (m_cur_byte << 3)) & 0xff;
|
||||
m_codec_status = CODEC_BUSY | CODEC_PRESENT | (m_counter << 14) | (m_cur_byte << 12) | (reg_data << 4);
|
||||
}
|
||||
break;
|
||||
|
||||
case 8: // Audio CODEC Status
|
||||
break;
|
||||
}
|
||||
}
|
62
src/mame/apple/burgundy.h
Normal file
62
src/mame/apple/burgundy.h
Normal file
@ -0,0 +1,62 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:R. Belmont
|
||||
/***************************************************************************
|
||||
|
||||
burgundy.h
|
||||
|
||||
"Burgundy" stereo 16-bit audio CODEC (iMac, Blue & White G3)
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MAME_APPLE_BURGUNDY_H
|
||||
#define MAME_APPLE_BURGUNDY_H
|
||||
|
||||
#pragma once
|
||||
|
||||
//**************************************************************************
|
||||
// TYPE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
// ======================> awacs_macrisc_device
|
||||
|
||||
class burgundy_device : public device_t, public device_sound_interface
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
burgundy_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
auto dma_output() { return m_output_cb.bind(); }
|
||||
auto dma_input() { return m_input_cb.bind(); }
|
||||
|
||||
virtual u32 read_macrisc(offs_t offset);
|
||||
virtual void write_macrisc(offs_t offset, u32 data);
|
||||
|
||||
protected:
|
||||
enum {
|
||||
ACTIVE_OUT = 0x01,
|
||||
ACTIVE_IN = 0x02
|
||||
};
|
||||
|
||||
// device-level overrides
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override;
|
||||
|
||||
devcb_read32 m_output_cb;
|
||||
devcb_write32 m_input_cb;
|
||||
|
||||
sound_stream *m_stream;
|
||||
|
||||
u32 m_registers[256];
|
||||
u8 m_active;
|
||||
u16 m_phase;
|
||||
u16 m_reg_addr, m_cur_byte, m_last_byte;
|
||||
u32 m_codec_status, m_last_codec_control;
|
||||
u8 m_counter;
|
||||
};
|
||||
|
||||
// device type definition
|
||||
DECLARE_DEVICE_TYPE(BURGUNDY, burgundy_device)
|
||||
|
||||
#endif // MAME_APPLE_BURGUNDY_H
|
273
src/mame/apple/dbdma.cpp
Normal file
273
src/mame/apple/dbdma.cpp
Normal file
@ -0,0 +1,273 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:R. Belmont
|
||||
/*
|
||||
Apple "Descriptor-Based DMA" channel device
|
||||
Emulation by R. Belmont
|
||||
*/
|
||||
|
||||
#include "emu.h"
|
||||
#include "dbdma.h"
|
||||
|
||||
#define LOG_GENERAL (1U << 0)
|
||||
|
||||
#define VERBOSE (0)
|
||||
#include "logmacro.h"
|
||||
|
||||
//**************************************************************************
|
||||
// DEVICE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
DEFINE_DEVICE_TYPE(DBDMA_CHANNEL, dbdma_device, "appledbdma", "Apple descriptor-based DMA channel")
|
||||
|
||||
static constexpr u16 STATUS_RUN = 0x8000;
|
||||
static constexpr u16 STATUS_PAUSE = 0x4000;
|
||||
static constexpr u16 STATUS_FLUSH = 0x2000;
|
||||
static constexpr u16 STATUS_WAKE = 0x1000;
|
||||
[[maybe_unused]] static constexpr u16 STATUS_DEAD = 0x0800;
|
||||
static constexpr u16 STATUS_ACTIVE = 0x0400;
|
||||
|
||||
//-------------------------------------------------
|
||||
// dbdma_device - constructor
|
||||
//-------------------------------------------------
|
||||
|
||||
dbdma_device::dbdma_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: device_t(mconfig, DBDMA_CHANNEL, tag, owner, clock),
|
||||
write_irq(*this)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
|
||||
void dbdma_device::device_start()
|
||||
{
|
||||
write_irq.resolve_safe();
|
||||
|
||||
save_item(NAME(m_status));
|
||||
save_item(NAME(m_command_pointer));
|
||||
save_item(NAME(m_intselect));
|
||||
save_item(NAME(m_branchselect));
|
||||
save_item(NAME(m_waitselect));
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_reset - device-specific reset
|
||||
//-------------------------------------------------
|
||||
|
||||
void dbdma_device::device_reset()
|
||||
{
|
||||
m_status = 0;
|
||||
m_command_pointer = 0;
|
||||
m_intselect = m_branchselect = m_waitselect = 0;
|
||||
}
|
||||
|
||||
// 00 = control (write only)
|
||||
// 04 = status (read only)
|
||||
// 0c = command pointer (read/write)
|
||||
// 10 = interrupt select
|
||||
// 14 = branch select
|
||||
// 18 = wait select
|
||||
|
||||
void dbdma_device::map(address_map &map)
|
||||
{
|
||||
map(0x00, 0x03).w(FUNC(dbdma_device::control_w));
|
||||
map(0x04, 0x07).r(FUNC(dbdma_device::status_r));
|
||||
map(0x0c, 0x0f).rw(FUNC(dbdma_device::cmdpointer_r), FUNC(dbdma_device::cmdpointer_w));
|
||||
map(0x10, 0x13).rw(FUNC(dbdma_device::intselect_r), FUNC(dbdma_device::intselect_w));
|
||||
map(0x14, 0x17).rw(FUNC(dbdma_device::branchselect_r), FUNC(dbdma_device::branchselect_w));
|
||||
map(0x18, 0x1b).rw(FUNC(dbdma_device::waitselect_r), FUNC(dbdma_device::waitselect_w));
|
||||
}
|
||||
|
||||
void dbdma_device::control_w(u32 data)
|
||||
{
|
||||
// the top 16 bits of data are a mask selecting which bits of
|
||||
// the status are changed by the write.
|
||||
const u16 mask = (data >> 16);
|
||||
|
||||
m_status &= (mask ^ 0xffff);
|
||||
m_status |= (data & mask);
|
||||
LOGMASKED(LOG_GENERAL, "%s: channel status/control to %04x (raw %08x)\n", tag(), m_status, data);
|
||||
|
||||
if (m_status & STATUS_RUN)
|
||||
{
|
||||
LOGMASKED(LOG_GENERAL, "%s: channel set to RUN, also setting ACTIVE\n", tag());
|
||||
m_status |= STATUS_ACTIVE;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_status &= ~STATUS_ACTIVE;
|
||||
}
|
||||
|
||||
if (m_status & STATUS_PAUSE)
|
||||
{
|
||||
m_status &= ~STATUS_ACTIVE;
|
||||
}
|
||||
|
||||
if (m_status & STATUS_FLUSH)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
if (m_status & STATUS_WAKE)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
u32 dbdma_device::status_r()
|
||||
{
|
||||
return m_status;
|
||||
}
|
||||
|
||||
u32 dbdma_device::cmdpointer_r()
|
||||
{
|
||||
return m_command_pointer;
|
||||
}
|
||||
|
||||
void dbdma_device::cmdpointer_w(u32 data)
|
||||
{
|
||||
if (!(m_status & STATUS_ACTIVE))
|
||||
{
|
||||
LOGMASKED(LOG_GENERAL, "%s: %08x to command pointer\n", tag(), swapendian_int32(data));
|
||||
m_command_pointer = data;
|
||||
|
||||
new_command();
|
||||
}
|
||||
}
|
||||
|
||||
u32 dbdma_device::intselect_r()
|
||||
{
|
||||
return m_intselect;
|
||||
}
|
||||
|
||||
void dbdma_device::intselect_w(u32 data)
|
||||
{
|
||||
m_intselect = data;
|
||||
}
|
||||
|
||||
u32 dbdma_device::branchselect_r()
|
||||
{
|
||||
return m_branchselect;
|
||||
}
|
||||
|
||||
void dbdma_device::branchselect_w(u32 data)
|
||||
{
|
||||
m_branchselect = data;
|
||||
}
|
||||
|
||||
u32 dbdma_device::waitselect_r()
|
||||
{
|
||||
return m_waitselect;
|
||||
}
|
||||
|
||||
void dbdma_device::waitselect_w(u32 data)
|
||||
{
|
||||
m_waitselect = data;
|
||||
}
|
||||
|
||||
u32 dbdma_device::dma_read(u32 offset)
|
||||
{
|
||||
step_program();
|
||||
return m_xfer_word;
|
||||
}
|
||||
|
||||
void dbdma_device::dma_write(u32 offset, u32 data)
|
||||
{
|
||||
m_xfer_word = data;
|
||||
step_program();
|
||||
}
|
||||
|
||||
void dbdma_device::step_program()
|
||||
{
|
||||
if ((m_status & STATUS_PAUSE) || !(m_status & STATUS_ACTIVE))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (m_opcode >> 28)
|
||||
{
|
||||
case 0: // OUTPUT MORE
|
||||
case 1: // OUTPUT LAST
|
||||
m_xfer_word = m_pci_memory->read_dword(m_address);
|
||||
m_address += 4;
|
||||
m_currentXfer += 4;
|
||||
break;
|
||||
|
||||
case 2: // INPUT MORE
|
||||
case 3: // INPUT LAST
|
||||
m_pci_memory->write_dword(m_address, m_xfer_word);
|
||||
m_address += 4;
|
||||
m_currentXfer += 4;
|
||||
break;
|
||||
|
||||
case 4: // STORE QUAD
|
||||
switch (m_xferLimit & 7)
|
||||
{
|
||||
case 1:
|
||||
m_pci_memory->write_byte(m_address, m_cmdDep);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
m_pci_memory->write_word(m_address, m_cmdDep);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
m_pci_memory->write_dword(m_address, m_cmdDep);
|
||||
break;
|
||||
}
|
||||
m_currentXfer += m_opcode & 7;
|
||||
break;
|
||||
|
||||
case 5: // LOAD QUAD
|
||||
switch (m_xferLimit & 7)
|
||||
{
|
||||
case 1:
|
||||
m_xfer_word = m_pci_memory->read_byte(m_address);
|
||||
m_pci_memory->write_byte(m_cmdDep, m_xfer_word);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
m_xfer_word = m_pci_memory->read_word(m_address);
|
||||
m_pci_memory->write_word(m_cmdDep, m_xfer_word);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
m_xfer_word = m_pci_memory->read_dword(m_address);
|
||||
m_pci_memory->write_dword(m_cmdDep, m_xfer_word);
|
||||
break;
|
||||
}
|
||||
m_currentXfer += m_opcode & 7;
|
||||
break;
|
||||
|
||||
case 6: // NOP
|
||||
break;
|
||||
|
||||
case 7: // STOP
|
||||
m_status &= ~STATUS_ACTIVE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_status & STATUS_ACTIVE)
|
||||
{
|
||||
if (m_currentXfer >= m_xferLimit)
|
||||
{
|
||||
m_command_pointer += 16;
|
||||
LOGMASKED(LOG_GENERAL, "%s: Advancing command pointer to %08x\n", tag(), m_command_pointer);
|
||||
new_command();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dbdma_device::new_command()
|
||||
{
|
||||
m_opcode = m_pci_memory->read_dword(m_command_pointer);
|
||||
m_address = m_pci_memory->read_dword(m_command_pointer + 4);
|
||||
m_cmdDep = m_pci_memory->read_dword(m_command_pointer + 8);
|
||||
m_statusCount = m_pci_memory->read_dword(m_command_pointer + 12);
|
||||
m_currentXfer = m_statusCount & 0xffff;
|
||||
m_xferLimit = m_opcode & 0xffff;
|
||||
|
||||
LOGMASKED(LOG_GENERAL, "%s: new command %08x %08x %08x %08x\n", tag(), m_opcode, m_address, m_cmdDep, m_statusCount);
|
||||
LOGMASKED(LOG_GENERAL, "%s: opcode %d\n", tag(), m_opcode >> 28);
|
||||
}
|
69
src/mame/apple/dbdma.h
Normal file
69
src/mame/apple/dbdma.h
Normal file
@ -0,0 +1,69 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:R. Belmont
|
||||
|
||||
#ifndef MAME_APPLE_DBDMA_H
|
||||
#define MAME_APPLE_DBDMA_H
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
// ======================> dbdma_device
|
||||
|
||||
class dbdma_device : public device_t
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
dbdma_device(const machine_config &mconfig, const char *tag, device_t *owner)
|
||||
: dbdma_device(mconfig, tag, owner, (uint32_t)0)
|
||||
{
|
||||
}
|
||||
|
||||
dbdma_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
u32 dma_read(u32 offset);
|
||||
void dma_write(u32 offset, u32 data);
|
||||
|
||||
auto irq_callback() { return write_irq.bind(); }
|
||||
|
||||
void set_address_space(address_space *space) { m_pci_memory = space; }
|
||||
|
||||
void map(address_map &map);
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
private:
|
||||
devcb_write_line write_irq;
|
||||
|
||||
address_space *m_pci_memory;
|
||||
|
||||
u16 m_status;
|
||||
u32 m_command_pointer;
|
||||
u32 m_intselect;
|
||||
u32 m_branchselect;
|
||||
u32 m_waitselect;
|
||||
u32 m_xfer_word;
|
||||
u32 m_opcode, m_address, m_cmdDep, m_statusCount;
|
||||
u16 m_currentXfer, m_xferLimit;
|
||||
|
||||
void control_w(u32 data);
|
||||
u32 status_r();
|
||||
u32 cmdpointer_r();
|
||||
void cmdpointer_w(u32 data);
|
||||
u32 intselect_r();
|
||||
void intselect_w(u32 data);
|
||||
u32 branchselect_r();
|
||||
void branchselect_w(u32 data);
|
||||
u32 waitselect_r();
|
||||
void waitselect_w(u32 data);
|
||||
|
||||
void step_program();
|
||||
void new_command();
|
||||
};
|
||||
|
||||
// device type definition
|
||||
DECLARE_DEVICE_TYPE(DBDMA_CHANNEL, dbdma_device)
|
||||
|
||||
#endif // MAME_APPLE_DBDMA_H
|
@ -6,7 +6,7 @@
|
||||
|
||||
These ASICs sit on the PCI bus and provide what came to be known as "Mac I/O",
|
||||
including:
|
||||
- A VIA to interface with Cuda
|
||||
- A VIA to interface with Cuda / an enhanced VIA that can speak SPI to interface with PG&E (O'Hare and later)
|
||||
- Serial
|
||||
- SWIM3 floppy
|
||||
- MESH SCSI ("Macintosh Enhanced SCSI Handler"), a 5394/96 clone with some features Apple didn't use removed)
|
||||
@ -22,6 +22,12 @@
|
||||
#include "bus/rs232/rs232.h"
|
||||
#include "formats/ap_dsk35.h"
|
||||
|
||||
#define LOG_GENERAL (1U << 0)
|
||||
#define LOG_IRQ (1U << 1)
|
||||
|
||||
#define VERBOSE (0)
|
||||
#include "logmacro.h"
|
||||
|
||||
static constexpr u32 C7M = 7833600;
|
||||
static constexpr u32 C15M = (C7M * 2);
|
||||
|
||||
@ -37,27 +43,51 @@ DEFINE_DEVICE_TYPE(GRAND_CENTRAL, grandcentral_device, "grndctrl", "Apple Grand
|
||||
//-------------------------------------------------
|
||||
// ADDRESS_MAP
|
||||
//-------------------------------------------------
|
||||
/*
|
||||
A "Kanga" G3 PowerBook says:
|
||||
16000 : VIA
|
||||
12000 : SCC Rd
|
||||
12000 : SCC Wr
|
||||
15000 : IWM/SWIM
|
||||
10000 : SCSI
|
||||
|
||||
DMA is at 8xxx (audio DMA at 88xx)
|
||||
ATA is at 20000
|
||||
/* Grand Central O'Hare Heathrow/Paddington
|
||||
0x10000 SCSI0 SCSI0 SCSI
|
||||
0x11000 MACE Ethernet (unused) "BigMac" Ethernet
|
||||
0x12000 SCC "compatibility" SCC compat SCC compat
|
||||
0x13000 SCC "MacRisc" SCC MacRisc SCC MacRisc
|
||||
0x14000 Audio Audio Audio
|
||||
0x15000 SWIM3 SWIM3 SWIM3
|
||||
0x16000 VIA VIA VIA
|
||||
0x17000 VIA VIA VIA
|
||||
0x18000 SCSI1 (unused) (unused)
|
||||
0x19000 Ethernet MAC PROM (unused) ADB Master Cell
|
||||
0x1a000 (external IOBus) (external IOBus) (external IOBus)
|
||||
0x1b000 (external IOBus) (external IOBus) (external IOBus)
|
||||
0x1c000 (external IOBus) (external IOBus) (external IOBus)
|
||||
0x1d000 (external IOBus) (external IOBus) (external IOBus)
|
||||
0x1e000 (external IOBus) (unused)
|
||||
0x1f000 (external IOBus) (unused)
|
||||
0x20000 (external IOBus) ATA bus 0 ATA bus 0
|
||||
0x21000 (external IOBus) ATA bus 1 ATA bus 1
|
||||
0x60000 (128K BAR, no) PRAM PRAM
|
||||
0x70000 (128K BAR, no) PRAM PRAM
|
||||
*/
|
||||
void grandcentral_device::map(address_map &map)
|
||||
{
|
||||
map(0x00000, 0x00fff).rw(FUNC(grandcentral_device::macio_r), FUNC(grandcentral_device::macio_w));
|
||||
map(0x08800, 0x0881f).m(m_dma_audio_out, FUNC(dbdma_device::map));
|
||||
map(0x08900, 0x0891f).m(m_dma_audio_in, FUNC(dbdma_device::map));
|
||||
map(0x12000, 0x12fff).rw(FUNC(grandcentral_device::scc_r), FUNC(grandcentral_device::scc_w));
|
||||
map(0x13000, 0x13fff).rw(FUNC(grandcentral_device::scc_macrisc_r), FUNC(grandcentral_device::scc_macrisc_w));
|
||||
map(0x14000, 0x140ff).rw(FUNC(heathrow_device::codec_r), FUNC(heathrow_device::codec_w));
|
||||
map(0x15000, 0x15fff).rw(FUNC(grandcentral_device::fdc_r), FUNC(grandcentral_device::fdc_w));
|
||||
map(0x16000, 0x17fff).rw(FUNC(grandcentral_device::mac_via_r), FUNC(grandcentral_device::mac_via_w));
|
||||
}
|
||||
|
||||
void heathrow_device::map(address_map &map)
|
||||
{
|
||||
map(0x00000, 0x00fff).rw(FUNC(heathrow_device::macio_r), FUNC(heathrow_device::macio_w));
|
||||
map(0x08800, 0x0881f).m(m_dma_audio_out, FUNC(dbdma_device::map));
|
||||
map(0x08900, 0x0891f).m(m_dma_audio_in, FUNC(dbdma_device::map));
|
||||
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(0x14020, 0x14023).r(FUNC(heathrow_device::unk_r));
|
||||
map(0x14000, 0x140ff).rw(FUNC(heathrow_device::codec_r), FUNC(heathrow_device::codec_w));
|
||||
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));
|
||||
map(0x60000, 0x7ffff).rw(FUNC(heathrow_device::nvram_r), FUNC(heathrow_device::nvram_w)).umask32(0x000000ff);
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
@ -71,16 +101,13 @@ void heathrow_device::device_add_mconfig(machine_config &config)
|
||||
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));
|
||||
m_via1->irq_handler().set(FUNC(heathrow_device::set_irq_line<18>));
|
||||
|
||||
AWACS(config, m_awacs, 45.1584_MHz_XTAL / 2);
|
||||
m_awacs->dma_output().set(FUNC(heathrow_device::sound_dma_output));
|
||||
m_awacs->dma_input().set(FUNC(heathrow_device::sound_dma_input));
|
||||
DBDMA_CHANNEL(config, m_dma_audio_out, 0);
|
||||
m_dma_audio_out->irq_callback().set(FUNC(heathrow_device::set_irq_line<8>));
|
||||
|
||||
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);
|
||||
DBDMA_CHANNEL(config, m_dma_audio_in, 0);
|
||||
m_dma_audio_in->irq_callback().set(FUNC(heathrow_device::set_irq_line<9>));
|
||||
|
||||
SWIM3(config, m_fdc, C15M);
|
||||
m_fdc->devsel_cb().set(FUNC(heathrow_device::devsel_w));
|
||||
@ -116,16 +143,21 @@ void heathrow_device::config_map(address_map &map)
|
||||
|
||||
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_irq(*this),
|
||||
write_pb4(*this),
|
||||
write_pb5(*this),
|
||||
write_cb2(*this),
|
||||
read_pb3(*this),
|
||||
read_codec(*this),
|
||||
write_codec(*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_dma_audio_in(*this, "dma_audin"),
|
||||
m_dma_audio_out(*this, "dma_audout"),
|
||||
m_pci_memory(*this, ":pci:00.0", AS_DATA),
|
||||
m_cur_floppy(nullptr),
|
||||
m_hdsel(0)
|
||||
{
|
||||
@ -158,41 +190,58 @@ ohare_device::ohare_device(const machine_config &mconfig, const char *tag, devic
|
||||
|
||||
void heathrow_device::common_init()
|
||||
{
|
||||
write_irq.resolve_safe();
|
||||
write_pb4.resolve_safe();
|
||||
write_pb5.resolve_safe();
|
||||
write_cb2.resolve_safe();
|
||||
read_pb3.resolve_safe(0);
|
||||
read_codec.resolve_safe(0);
|
||||
write_codec.resolve_safe();
|
||||
|
||||
m_6015_timer = timer_alloc(FUNC(heathrow_device::mac_6015_tick), this);
|
||||
m_6015_timer->adjust(attotime::never);
|
||||
save_item(NAME(m_hdsel));
|
||||
m_dma_audio_out->set_address_space(m_pci_memory);
|
||||
|
||||
add_map(0x80000, M_MEM, FUNC(heathrow_device::map));
|
||||
command = 2; // enable our memory range
|
||||
revision = 1;
|
||||
|
||||
m_InterruptEvents = m_InterruptMask = m_InterruptLevels = 0;
|
||||
m_InterruptEvents2 = m_InterruptMask2 = m_InterruptLevels2 = 0;
|
||||
recalc_irqs();
|
||||
|
||||
save_item(NAME(m_hdsel));
|
||||
save_item(NAME(m_InterruptEvents));
|
||||
save_item(NAME(m_InterruptMask));
|
||||
save_item(NAME(m_InterruptLevels));
|
||||
save_item(NAME(m_InterruptEvents2));
|
||||
save_item(NAME(m_InterruptMask2));
|
||||
save_item(NAME(m_InterruptLevels2));
|
||||
save_item(NAME(m_nvram));
|
||||
}
|
||||
|
||||
void heathrow_device::device_start()
|
||||
{
|
||||
common_init();
|
||||
add_map(0x80000, M_MEM, FUNC(heathrow_device::map));
|
||||
set_ids(0x106b0010, 0x01, 0xff000001, 0x000000);
|
||||
}
|
||||
|
||||
void paddington_device::device_start()
|
||||
{
|
||||
common_init();
|
||||
add_map(0x80000, M_MEM, FUNC(heathrow_device::map));
|
||||
set_ids(0x106b0017, 0x01, 0xff000001, 0x000000);
|
||||
}
|
||||
|
||||
void grandcentral_device::device_start()
|
||||
{
|
||||
common_init();
|
||||
add_map(0x20000, M_MEM, FUNC(heathrow_device::map)); // Grand Central only has 128K of BAR space, the others have 512K
|
||||
set_ids(0x106b0002, 0x01, 0xff000001, 0x000000);
|
||||
}
|
||||
|
||||
void ohare_device::device_start()
|
||||
{
|
||||
common_init();
|
||||
add_map(0x80000, M_MEM, FUNC(heathrow_device::map));
|
||||
set_ids(0x106b0007, 0x01, 0xff000001, 0x000000);
|
||||
}
|
||||
|
||||
@ -202,18 +251,9 @@ void ohare_device::device_start()
|
||||
|
||||
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;
|
||||
@ -248,10 +288,6 @@ void heathrow_device::via_out_b(u8 data)
|
||||
write_pb5(BIT(data, 5));
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(heathrow_device::via1_irq)
|
||||
{
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(heathrow_device::cb1_w)
|
||||
{
|
||||
m_via1->write_cb1(state);
|
||||
@ -353,13 +389,126 @@ void heathrow_device::devsel_w(u8 devsel)
|
||||
|
||||
u32 heathrow_device::macio_r(offs_t offset)
|
||||
{
|
||||
// InterruptLevels = live status of all interrupt lines
|
||||
// InterruptMask = mask to determine which bits of InterruptLevels matter
|
||||
// InterruptEvents = interrupts allowed to fire by InterruptMask
|
||||
// printf("macio_r: offset %x (%x)\n", offset, offset*4);
|
||||
switch (offset << 2)
|
||||
{
|
||||
case 0x10:
|
||||
return swapendian_int32(m_InterruptEvents2 & m_InterruptMask2);
|
||||
case 0x14:
|
||||
return swapendian_int32(m_InterruptMask2);
|
||||
case 0x1c:
|
||||
return swapendian_int32(m_InterruptLevels2);
|
||||
case 0x20:
|
||||
return swapendian_int32(m_InterruptEvents & m_InterruptMask);
|
||||
case 0x24:
|
||||
return swapendian_int32(m_InterruptMask);
|
||||
case 0x2c:
|
||||
return swapendian_int32(m_InterruptLevels);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void heathrow_device::macio_w(offs_t offset, u32 data, u32 mem_mask)
|
||||
{
|
||||
data = swapendian_int32(data);
|
||||
mem_mask = swapendian_int32(mem_mask);
|
||||
// printf("macio_w: offset %x (%x) data %08x mask %08x\n", offset, offset*4, data, mem_mask);
|
||||
switch (offset << 2)
|
||||
{
|
||||
case 0x14:
|
||||
m_InterruptMask2 = data;
|
||||
recalc_irqs();
|
||||
break;
|
||||
case 0x18: // InterruptClear
|
||||
// which interrupt mode?
|
||||
if (BIT(m_InterruptMask2, 31))
|
||||
{
|
||||
// in Mode 1, "1" to bit 31 clears all active interrupts
|
||||
if (BIT(data, 31))
|
||||
{
|
||||
m_InterruptEvents2 = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_InterruptEvents2 &= (data ^ 0xffffffff);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_InterruptEvents2 &= (data ^ 0xffffffff);
|
||||
}
|
||||
recalc_irqs();
|
||||
break;
|
||||
case 0x24:
|
||||
m_InterruptMask = data;
|
||||
recalc_irqs();
|
||||
break;
|
||||
case 0x28: // InterruptClear
|
||||
// which interrupt mode?
|
||||
if (BIT(m_InterruptMask, 31))
|
||||
{
|
||||
// in Mode 1, "1" to bit 31 clears all active interrupts
|
||||
if (BIT(data, 31))
|
||||
{
|
||||
m_InterruptEvents = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_InterruptEvents &= (data ^ 0xffffffff);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_InterruptEvents &= (data ^ 0xffffffff);
|
||||
}
|
||||
recalc_irqs();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void heathrow_device::recalc_irqs()
|
||||
{
|
||||
LOGMASKED(LOG_IRQ, "%s recalc_irqs: events %08x levels %08x mask %08x\n", tag(), m_InterruptEvents, m_InterruptLevels, m_InterruptMask);
|
||||
m_InterruptEvents = m_InterruptLevels & m_InterruptMask;
|
||||
m_InterruptEvents2 = m_InterruptLevels2 & m_InterruptMask2;
|
||||
if (m_InterruptEvents || m_InterruptEvents2)
|
||||
{
|
||||
write_irq(ASSERT_LINE);
|
||||
}
|
||||
else
|
||||
{
|
||||
write_irq(CLEAR_LINE);
|
||||
}
|
||||
}
|
||||
|
||||
template<int bit> WRITE_LINE_MEMBER(heathrow_device::set_irq_line)
|
||||
{
|
||||
if (bit < 32)
|
||||
{
|
||||
if (state == ASSERT_LINE)
|
||||
{
|
||||
m_InterruptLevels |= (1 << bit);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_InterruptLevels &= ((1 << bit) ^ 0xffffffff);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (state == ASSERT_LINE)
|
||||
{
|
||||
m_InterruptLevels2 |= (1 << (bit-32));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_InterruptLevels2 &= ((1 << (bit-32)) ^ 0xffffffff);
|
||||
}
|
||||
}
|
||||
recalc_irqs();
|
||||
}
|
||||
|
||||
u8 heathrow_device::fdc_r(offs_t offset)
|
||||
@ -374,12 +523,12 @@ void heathrow_device::fdc_w(offs_t offset, u8 data)
|
||||
|
||||
u8 heathrow_device::nvram_r(offs_t offset)
|
||||
{
|
||||
return m_nvram[offset >> 2];
|
||||
return m_nvram[offset>>2];
|
||||
}
|
||||
|
||||
void heathrow_device::nvram_w(offs_t offset, u8 data)
|
||||
{
|
||||
m_nvram[offset >> 2] = data;
|
||||
m_nvram[offset>>2] = data;
|
||||
}
|
||||
|
||||
u16 heathrow_device::scc_r(offs_t offset)
|
||||
@ -430,21 +579,23 @@ void heathrow_device::scc_macrisc_w(offs_t offset, u8 data)
|
||||
}
|
||||
}
|
||||
|
||||
u32 heathrow_device::unk_r(offs_t offset)
|
||||
// Audio support
|
||||
uint32_t heathrow_device::codec_r(offs_t offset)
|
||||
{
|
||||
m_toggle ^= 0xffffffff;
|
||||
return m_toggle;
|
||||
return read_codec(offset);
|
||||
}
|
||||
|
||||
// *****************************************************
|
||||
// DMA
|
||||
// *****************************************************
|
||||
|
||||
u32 heathrow_device::sound_dma_output(offs_t offset)
|
||||
void heathrow_device::codec_w(offs_t offset, uint32_t data)
|
||||
{
|
||||
return 0;
|
||||
write_codec(offset, data);
|
||||
}
|
||||
|
||||
void heathrow_device::sound_dma_input(offs_t offset, u32 value)
|
||||
u32 heathrow_device::codec_dma_read(u32 offset)
|
||||
{
|
||||
return m_dma_audio_out->dma_read(offset);
|
||||
}
|
||||
|
||||
void heathrow_device::codec_dma_write(u32 offset, u32 data)
|
||||
{
|
||||
m_dma_audio_in->dma_write(offset, data);
|
||||
}
|
||||
|
@ -6,13 +6,14 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "dbdma.h"
|
||||
|
||||
#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
|
||||
|
||||
@ -24,19 +25,32 @@ public:
|
||||
heathrow_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
// interface routines
|
||||
auto irq_callback() { return write_irq.bind(); }
|
||||
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);
|
||||
auto codec_r_callback() { return read_codec.bind(); }
|
||||
auto codec_w_callback() { return write_codec.bind(); }
|
||||
|
||||
virtual void map(address_map &map);
|
||||
|
||||
template <typename... T> void set_maincpu_tag(T &&... args) { m_maincpu.set_tag(std::forward<T>(args)...); }
|
||||
template <typename... T> void set_pci_root_tag(T &&... args) { m_pci_memory.set_tag(std::forward<T>(args)...); }
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER(cb1_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(cb2_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(scc_irq_w);
|
||||
|
||||
template <int bit> DECLARE_WRITE_LINE_MEMBER(set_irq_line);
|
||||
|
||||
u32 codec_dma_read(u32 offset);
|
||||
void codec_dma_write(u32 offset, u32 data);
|
||||
|
||||
u32 codec_r(offs_t offset);
|
||||
void codec_w(offs_t offset, u32 data);
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start() override;
|
||||
@ -47,40 +61,6 @@ protected:
|
||||
|
||||
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<cpu_device> m_maincpu;
|
||||
required_device<via6522_device> m_via1;
|
||||
required_device<applefdintf_device> m_fdc;
|
||||
required_device_array<floppy_connector, 2> m_floppy;
|
||||
required_device<awacs_device> m_awacs;
|
||||
required_device<z80scc_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);
|
||||
|
||||
@ -98,12 +78,46 @@ private:
|
||||
u8 scc_macrisc_r(offs_t offset);
|
||||
void scc_macrisc_w(offs_t offset, u8 data);
|
||||
|
||||
u32 m_toggle;
|
||||
u32 unk_r(offs_t offset);
|
||||
u16 mac_via_r(offs_t offset);
|
||||
void mac_via_w(offs_t offset, u16 data, u16 mem_mask);
|
||||
|
||||
// DMA
|
||||
u32 sound_dma_output(offs_t offset);
|
||||
void sound_dma_input(offs_t offset, u32 value);
|
||||
devcb_write_line write_irq, write_pb4, write_pb5, write_cb2;
|
||||
devcb_read_line read_pb3;
|
||||
|
||||
devcb_read32 read_codec;
|
||||
devcb_write32 write_codec;
|
||||
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<via6522_device> m_via1;
|
||||
required_device<applefdintf_device> m_fdc;
|
||||
required_device_array<floppy_connector, 2> m_floppy;
|
||||
required_device<z80scc_device> m_scc;
|
||||
required_device<dbdma_device> m_dma_audio_in, m_dma_audio_out;
|
||||
required_address_space m_pci_memory;
|
||||
|
||||
private:
|
||||
floppy_image_device *m_cur_floppy = nullptr;
|
||||
int m_hdsel;
|
||||
|
||||
u8 m_nvram[0x20000];
|
||||
|
||||
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);
|
||||
|
||||
void phases_w(u8 phases);
|
||||
void devsel_w(u8 devsel);
|
||||
|
||||
u32 m_toggle;
|
||||
|
||||
// Interrupts
|
||||
void recalc_irqs();
|
||||
u32 m_InterruptEvents, m_InterruptMask, m_InterruptLevels;
|
||||
u32 m_InterruptEvents2, m_InterruptMask2, m_InterruptLevels2;
|
||||
};
|
||||
|
||||
class paddington_device : public heathrow_device
|
||||
@ -123,6 +137,8 @@ public:
|
||||
// construction/destruction
|
||||
grandcentral_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
|
||||
|
||||
void map(address_map &map) override;
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start() override;
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "machine/pci.h"
|
||||
#include "machine/pci-ide.h"
|
||||
#include "machine/ram.h"
|
||||
#include "burgundy.h"
|
||||
#include "cuda.h"
|
||||
#include "heathrow.h"
|
||||
#include "macadb.h"
|
||||
@ -54,6 +55,11 @@ private:
|
||||
m_maincpu->set_input_line(INPUT_LINE_HALT, state);
|
||||
m_maincpu->set_input_line(INPUT_LINE_RESET, state);
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(irq_w)
|
||||
{
|
||||
m_maincpu->set_input_line(PPC_IRQ, state);
|
||||
}
|
||||
};
|
||||
|
||||
imac_state::imac_state(const machine_config &mconfig, device_type type, const char *tag) :
|
||||
@ -116,6 +122,8 @@ void imac_state::imac(machine_config &config)
|
||||
|
||||
paddington_device &paddington(PADDINGTON(config, "pci:10.0", 0));
|
||||
paddington.set_maincpu_tag("maincpu");
|
||||
paddington.set_pci_root_tag(":pci:00.0", AS_DATA);
|
||||
paddington.irq_callback().set(FUNC(imac_state::irq_w));
|
||||
|
||||
MACADB(config, m_macadb, 15.6672_MHz_XTAL);
|
||||
|
||||
@ -151,6 +159,17 @@ void imac_state::imac(machine_config &config)
|
||||
RAM(config, m_ram);
|
||||
m_ram->set_default_size("32M");
|
||||
m_ram->set_extra_options("32M,64M,128M");
|
||||
|
||||
burgundy_device &burgundy(BURGUNDY(config, "codec", 45.1584_MHz_XTAL / 2));
|
||||
burgundy.dma_output().set(paddington, FUNC(heathrow_device::codec_dma_read));
|
||||
|
||||
paddington.codec_r_callback().set(burgundy, FUNC(burgundy_device::read_macrisc));
|
||||
paddington.codec_w_callback().set(burgundy, FUNC(burgundy_device::write_macrisc));
|
||||
|
||||
SPEAKER(config, "lspeaker").front_left();
|
||||
SPEAKER(config, "rspeaker").front_right();
|
||||
burgundy.add_route(0, "lspeaker", 1.0);
|
||||
burgundy.add_route(1, "rspeaker", 1.0);
|
||||
}
|
||||
|
||||
ROM_START(imac)
|
||||
|
@ -52,6 +52,7 @@
|
||||
#include "machine/ram.h"
|
||||
#include "sound/cdda.h"
|
||||
|
||||
#include "awacs_macrisc.h"
|
||||
#include "bandit.h"
|
||||
#include "cuda.h"
|
||||
#include "heathrow.h"
|
||||
@ -59,15 +60,15 @@
|
||||
#include "softlist.h"
|
||||
#include "speaker.h"
|
||||
|
||||
class macpci_state : public driver_device
|
||||
class pippin_state : public driver_device
|
||||
{
|
||||
public:
|
||||
void pippin(machine_config &config);
|
||||
|
||||
macpci_state(const machine_config &mconfig, device_type type, const char *tag);
|
||||
pippin_state(const machine_config &mconfig, device_type type, const char *tag);
|
||||
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<aspen_host_device> m_bandit;
|
||||
required_device<aspen_host_device> m_aspen;
|
||||
required_device<cuda_device> m_cuda;
|
||||
required_device<macadb_device> m_macadb;
|
||||
required_device<ram_device> m_ram;
|
||||
@ -85,29 +86,34 @@ private:
|
||||
m_maincpu->set_input_line(INPUT_LINE_HALT, state);
|
||||
m_maincpu->set_input_line(INPUT_LINE_RESET, state);
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(irq_w)
|
||||
{
|
||||
m_maincpu->set_input_line(PPC_IRQ, state);
|
||||
}
|
||||
};
|
||||
|
||||
macpci_state::macpci_state(const machine_config &mconfig, device_type type, const char *tag) :
|
||||
pippin_state::pippin_state(const machine_config &mconfig, device_type type, const char *tag) :
|
||||
driver_device(mconfig, type, tag),
|
||||
m_maincpu(*this, "maincpu"),
|
||||
m_bandit(*this, "pci:00.0"),
|
||||
m_aspen(*this, "pci:00.0"),
|
||||
m_cuda(*this, "cuda"),
|
||||
m_macadb(*this, "macadb"),
|
||||
m_ram(*this, RAM_TAG)
|
||||
{
|
||||
}
|
||||
|
||||
void macpci_state::machine_start()
|
||||
void pippin_state::machine_start()
|
||||
{
|
||||
}
|
||||
|
||||
void macpci_state::machine_reset()
|
||||
void pippin_state::machine_reset()
|
||||
{
|
||||
// the PPC can't run until Cuda's ready
|
||||
m_maincpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
|
||||
}
|
||||
|
||||
void macpci_state::pippin_map(address_map &map)
|
||||
void pippin_state::pippin_map(address_map &map)
|
||||
{
|
||||
map(0x00000000, 0x005fffff).ram();
|
||||
|
||||
@ -118,19 +124,20 @@ void macpci_state::pippin_map(address_map &map)
|
||||
map(0x03c00000, 0x03c01007).ram();
|
||||
|
||||
map(0x40000000, 0x403fffff).rom().region("bootrom", 0).mirror(0x0fc00000); // mirror of ROM for 680x0 emulation
|
||||
map(0x40000000, 0x40000000).lr8(NAME([]() { return 0x80; })); // hack to make flash ROM status check pass (causes 0xe1 to be written to VRAM, which is important later)
|
||||
map(0x5ffffffc, 0x5fffffff).lr32(NAME([](offs_t offset) { return 0xa55a7001; }));
|
||||
|
||||
map(0xf00dfff8, 0xf00dffff).lr64(NAME([](offs_t offset) { return (uint64_t)0xe1 << 32; })); // PC=0xfff04810
|
||||
map(0xf0000000, 0xf00fffff).ram(); // VRAM
|
||||
|
||||
map(0xffc00000, 0xffffffff).rom().region("bootrom", 0);
|
||||
}
|
||||
|
||||
void macpci_state::cdmcu_mem(address_map &map)
|
||||
void pippin_state::cdmcu_mem(address_map &map)
|
||||
{
|
||||
map(0x0000, 0xffff).rom().region("cdrom", 0);
|
||||
}
|
||||
|
||||
void macpci_state::cdmcu_data(address_map &map)
|
||||
void pippin_state::cdmcu_data(address_map &map)
|
||||
{
|
||||
map(0x0000, 0x0001).noprw();
|
||||
map(0x0003, 0x0003).noprw();
|
||||
@ -155,14 +162,14 @@ void macpci_state::cdmcu_data(address_map &map)
|
||||
static INPUT_PORTS_START( pippin )
|
||||
INPUT_PORTS_END
|
||||
|
||||
void macpci_state::pippin(machine_config &config)
|
||||
void pippin_state::pippin(machine_config &config)
|
||||
{
|
||||
/* basic machine hardware */
|
||||
PPC603(config, m_maincpu, 66000000);
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &macpci_state::pippin_map);
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &pippin_state::pippin_map);
|
||||
|
||||
PCI_ROOT(config, "pci", 0);
|
||||
ASPEN(config, m_bandit, 66000000, "maincpu").set_dev_offset(1);
|
||||
ASPEN(config, m_aspen, 66000000, "maincpu").set_dev_offset(1);
|
||||
|
||||
cdrom_image_device &cdrom(CDROM(config, "cdrom", 0));
|
||||
cdrom.set_interface("pippin_cdrom");
|
||||
@ -173,11 +180,24 @@ void macpci_state::pippin(machine_config &config)
|
||||
|
||||
grandcentral_device &grandcentral(GRAND_CENTRAL(config, "pci:0d.0", 0));
|
||||
grandcentral.set_maincpu_tag("maincpu");
|
||||
grandcentral.set_pci_root_tag(":pci:00.0", AS_DATA);
|
||||
grandcentral.irq_callback().set(FUNC(pippin_state::irq_w));
|
||||
|
||||
awacs_macrisc_device &awacs(AWACS_MACRISC(config, "codec", 45.1584_MHz_XTAL / 2));
|
||||
awacs.dma_output().set(grandcentral, FUNC(heathrow_device::codec_dma_read));
|
||||
|
||||
grandcentral.codec_r_callback().set(awacs, FUNC(awacs_macrisc_device::read_macrisc));
|
||||
grandcentral.codec_w_callback().set(awacs, FUNC(awacs_macrisc_device::write_macrisc));
|
||||
|
||||
SPEAKER(config, "lspeaker").front_left();
|
||||
SPEAKER(config, "rspeaker").front_right();
|
||||
awacs.add_route(0, "lspeaker", 1.0);
|
||||
awacs.add_route(1, "rspeaker", 1.0);
|
||||
|
||||
MACADB(config, m_macadb, 15.6672_MHz_XTAL);
|
||||
|
||||
CUDA(config, m_cuda, CUDA_341S0060);
|
||||
m_cuda->reset_callback().set(FUNC(macpci_state::cuda_reset_w));
|
||||
m_cuda->reset_callback().set(FUNC(pippin_state::cuda_reset_w));
|
||||
m_cuda->linechange_callback().set(m_macadb, FUNC(macadb_device::adb_linechange_w));
|
||||
m_cuda->via_clock_callback().set(grandcentral, FUNC(heathrow_device::cb1_w));
|
||||
m_cuda->via_data_callback().set(grandcentral, FUNC(heathrow_device::cb2_w));
|
||||
@ -190,8 +210,8 @@ void macpci_state::pippin(machine_config &config)
|
||||
grandcentral.cb2_callback().set(m_cuda, FUNC(cuda_device::set_via_data));
|
||||
|
||||
mn1880_device &cdmcu(MN1880(config, "cdmcu", 8388608)); // type and clock unknown
|
||||
cdmcu.set_addrmap(AS_PROGRAM, &macpci_state::cdmcu_mem);
|
||||
cdmcu.set_addrmap(AS_DATA, &macpci_state::cdmcu_data);
|
||||
cdmcu.set_addrmap(AS_PROGRAM, &pippin_state::cdmcu_mem);
|
||||
cdmcu.set_addrmap(AS_DATA, &pippin_state::cdmcu_data);
|
||||
cdmcu.set_disable();
|
||||
}
|
||||
|
||||
@ -235,4 +255,4 @@ ROM_END
|
||||
/* Driver */
|
||||
|
||||
/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */
|
||||
COMP( 1996, pippin, 0, 0, pippin, pippin, macpci_state, empty_init, "Apple / Bandai", "Pippin @mark", MACHINE_NOT_WORKING)
|
||||
COMP( 1996, pippin, 0, 0, pippin, pippin, pippin_state, empty_init, "Apple / Bandai", "Pippin @mark", MACHINE_NOT_WORKING)
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "machine/pci.h"
|
||||
#include "machine/pci-ide.h"
|
||||
#include "machine/ram.h"
|
||||
#include "awacs_macrisc.h"
|
||||
#include "cuda.h"
|
||||
#include "heathrow.h"
|
||||
#include "macadb.h"
|
||||
@ -53,6 +54,11 @@ private:
|
||||
m_maincpu->set_input_line(INPUT_LINE_HALT, state);
|
||||
m_maincpu->set_input_line(INPUT_LINE_RESET, state);
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(irq_w)
|
||||
{
|
||||
m_maincpu->set_input_line(PPC_IRQ, state);
|
||||
}
|
||||
};
|
||||
|
||||
pwrmacg3_state::pwrmacg3_state(const machine_config &mconfig, device_type type, const char *tag) :
|
||||
@ -123,6 +129,7 @@ void pwrmacg3_state::pwrmacg3(machine_config &config)
|
||||
|
||||
heathrow_device &heathrow(HEATHROW(config, "pci:10.0", 0));
|
||||
heathrow.set_maincpu_tag("maincpu");
|
||||
heathrow.set_pci_root_tag(":pci:00.0", AS_DATA);
|
||||
|
||||
MACADB(config, m_macadb, 15.6672_MHz_XTAL);
|
||||
|
||||
@ -134,6 +141,7 @@ void pwrmacg3_state::pwrmacg3(machine_config &config)
|
||||
m_macadb->adb_data_callback().set(m_cuda, FUNC(cuda_device::set_adb_line));
|
||||
config.set_perfect_quantum(m_maincpu);
|
||||
|
||||
heathrow.irq_callback().set(FUNC(pwrmacg3_state::irq_w));
|
||||
heathrow.pb3_callback().set(m_cuda, FUNC(cuda_device::get_treq));
|
||||
heathrow.pb4_callback().set(m_cuda, FUNC(cuda_device::set_byteack));
|
||||
heathrow.pb5_callback().set(m_cuda, FUNC(cuda_device::set_tip));
|
||||
@ -163,6 +171,17 @@ void pwrmacg3_state::pwrmacg3(machine_config &config)
|
||||
RAM(config, m_ram);
|
||||
m_ram->set_default_size("32M");
|
||||
m_ram->set_extra_options("32M,64M,96M,128M,256M");
|
||||
|
||||
screamer_device &screamer(SCREAMER(config, "codec", 45.1584_MHz_XTAL / 2));
|
||||
screamer.dma_output().set(heathrow, FUNC(heathrow_device::codec_dma_read));
|
||||
|
||||
heathrow.codec_r_callback().set(screamer, FUNC(screamer_device::read_macrisc));
|
||||
heathrow.codec_w_callback().set(screamer, FUNC(screamer_device::write_macrisc));
|
||||
|
||||
SPEAKER(config, "lspeaker").front_left();
|
||||
SPEAKER(config, "rspeaker").front_right();
|
||||
screamer.add_route(0, "lspeaker", 1.0);
|
||||
screamer.add_route(1, "rspeaker", 1.0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user