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:
arbee 2023-04-29 21:21:49 -04:00
parent 47202637e6
commit 59baa6640b
14 changed files with 1285 additions and 134 deletions

View File

@ -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;
}

View File

@ -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;
};

View 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]);
}

View 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

View File

@ -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
View 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
View 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
View 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
View 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

View File

@ -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);
}

View File

@ -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;

View File

@ -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)

View File

@ -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)

View File

@ -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);
}
/*