mirror of
https://github.com/dingusdev/dingusppc.git
synced 2025-01-11 05:29:43 +00:00
Add interrupt processing to AMIC.
This commit is contained in:
parent
d9d8384d4a
commit
d61d1d71eb
@ -1,6 +1,6 @@
|
||||
/*
|
||||
DingusPPC - The Experimental PowerPC Macintosh emulator
|
||||
Copyright (C) 2018-21 divingkatae and maximum
|
||||
Copyright (C) 2018-22 divingkatae and maximum
|
||||
(theweirdo) spatium
|
||||
|
||||
(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
|
||||
@ -24,6 +24,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
Author: Max Poliakovski
|
||||
*/
|
||||
|
||||
#include <cpu/ppc/ppcemu.h>
|
||||
#include <cpu/ppc/ppcmmu.h>
|
||||
#include <devices/common/scsi/ncr53c94.h>
|
||||
#include <devices/common/viacuda.h>
|
||||
@ -41,7 +42,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
#include <loguru.hpp>
|
||||
#include <memory>
|
||||
|
||||
AMIC::AMIC()
|
||||
AMIC::AMIC() : MMIODevice()
|
||||
{
|
||||
this->name = "Apple Memory-mapped I/O Controller";
|
||||
|
||||
@ -72,14 +73,6 @@ AMIC::AMIC()
|
||||
this->swim3 = std::unique_ptr<Swim3::Swim3Ctrl> (new Swim3::Swim3Ctrl());
|
||||
}
|
||||
|
||||
bool AMIC::supports_type(HWCompType type) {
|
||||
if (type == HWCompType::MMIO_DEV) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t AMIC::read(uint32_t reg_start, uint32_t offset, int size)
|
||||
{
|
||||
uint32_t phase_val;
|
||||
@ -129,6 +122,8 @@ uint32_t AMIC::read(uint32_t reg_start, uint32_t offset, int size)
|
||||
return this->def_vid->get_video_mode();
|
||||
case AMICReg::Monitor_Id:
|
||||
return this->mon_id;
|
||||
case AMICReg::Int_Ctrl:
|
||||
return (this->int_ctrl & 0xC0) | (this->dev_irq_lines & 0x3F);
|
||||
case AMICReg::Diag_Reg:
|
||||
return 0xFFU; // this value allows the machine to boot normally
|
||||
case AMICReg::SCSI_DMA_Ctrl:
|
||||
@ -248,7 +243,13 @@ void AMIC::write(uint32_t reg_start, uint32_t offset, uint32_t value, int size)
|
||||
}
|
||||
break;
|
||||
case AMICReg::Int_Ctrl:
|
||||
LOG_F(INFO, "AMIC Interrupt Control Register set to %X", value);
|
||||
// reset CPU interrupt bit if requested
|
||||
if (value & AMIC_INT_CLR) {
|
||||
this->int_ctrl &= ~AMIC_INT_CLR;
|
||||
}
|
||||
// keep interrupt mode bit
|
||||
// and discard read-only IQR state bits
|
||||
this->int_ctrl |= value & AMIC_INT_MODE;
|
||||
break;
|
||||
case AMICReg::DMA_Base_Addr_0:
|
||||
case AMICReg::DMA_Base_Addr_1:
|
||||
@ -290,6 +291,40 @@ void AMIC::write(uint32_t reg_start, uint32_t offset, uint32_t value, int size)
|
||||
}
|
||||
}
|
||||
|
||||
// ======================== Interrupt related stuff ==========================
|
||||
uint32_t AMIC::register_dev_int(IntSrc src_id) {
|
||||
switch (src_id) {
|
||||
case IntSrc::VIA_CUDA:
|
||||
return 1;
|
||||
default:
|
||||
ABORT_F("AMIC: unknown interrupt source %d", src_id);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t AMIC::register_dma_int(IntSrc src_id) {
|
||||
ABORT_F("AMIC: register_dma_int() not implemented");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AMIC::ack_int(uint32_t irq_id, uint8_t irq_line_state) {
|
||||
if (this->int_ctrl & AMIC_INT_MODE) { // 68k interrupt emulation mode?
|
||||
this->int_ctrl |= 0x80; // set CPU interrupt bit
|
||||
if (irq_line_state) {
|
||||
this->dev_irq_lines |= irq_id;
|
||||
} else {
|
||||
this->dev_irq_lines &= ~irq_id;
|
||||
}
|
||||
ppc_ext_int();
|
||||
} else {
|
||||
ABORT_F("AMIC: interrupt mode 0 not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
void AMIC::ack_dma_int(uint32_t irq_id, uint8_t irq_line_state) {
|
||||
ABORT_F("AMIC: ack_dma_int() not implemented");
|
||||
}
|
||||
|
||||
// =========================== DMA related stuff =============================
|
||||
AmicSndOutDma::AmicSndOutDma()
|
||||
{
|
||||
|
@ -24,6 +24,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
#ifndef AMIC_H
|
||||
#define AMIC_H
|
||||
|
||||
#include <devices/common/hwinterrupt.h>
|
||||
#include <devices/common/mmiodevice.h>
|
||||
#include <devices/common/scsi/ncr53c94.h>
|
||||
#include <devices/common/viacuda.h>
|
||||
@ -37,12 +38,16 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
#include <cinttypes>
|
||||
#include <memory>
|
||||
|
||||
/** Interrupt related constants. */
|
||||
#define AMIC_INT_CLR 0x80 // clears CPU interrupt
|
||||
#define AMIC_INT_MODE 0x40 // interrupt mode: 0 - native, 1 - 68k-style
|
||||
|
||||
/** AMIC sound buffers are located at fixed offsets from DMA base. */
|
||||
#define AMIC_SND_BUF0_OFFS 0x10000
|
||||
#define AMIC_SND_BUF1_OFFS 0x12000
|
||||
|
||||
// PDM HWInit source defines two constants: kExpBit = 0x80 and kCmdBit = 0x40
|
||||
// I don't know what they means but it seems that their combination will
|
||||
// I don't know what they mean but it seems that their combination will
|
||||
// cause sound control parameters to be transferred to the sound chip.
|
||||
#define PDM_SND_CTRL_VALID 0xC0
|
||||
|
||||
@ -110,6 +115,7 @@ enum AMICReg : uint32_t {
|
||||
Pixel_Depth = 0x28001,
|
||||
Monitor_Id = 0x28002,
|
||||
|
||||
// Interrupt registers
|
||||
Int_Ctrl = 0x2A000,
|
||||
|
||||
// Undocumented diagnostics register
|
||||
@ -131,19 +137,24 @@ enum AMICReg : uint32_t {
|
||||
};
|
||||
|
||||
/** Apple Memory-mapped I/O controller device. */
|
||||
class AMIC : public MMIODevice {
|
||||
class AMIC : public MMIODevice, public InterruptCtrl {
|
||||
public:
|
||||
AMIC();
|
||||
~AMIC() = default;
|
||||
|
||||
bool supports_type(HWCompType type);
|
||||
bool supports_type(HWCompType type) {
|
||||
return (type == HWCompType::MMIO_DEV) || (type == HWCompType::INT_CTRL);
|
||||
};
|
||||
|
||||
/* MMIODevice methods */
|
||||
uint32_t read(uint32_t reg_start, uint32_t offset, int size);
|
||||
void write(uint32_t reg_start, uint32_t offset, uint32_t value, int size);
|
||||
|
||||
protected:
|
||||
void dma_reg_write(uint32_t offset, uint32_t value, int size);
|
||||
// InterruptCtrl methods
|
||||
uint32_t register_dev_int(IntSrc src_id);
|
||||
uint32_t register_dma_int(IntSrc src_id);
|
||||
void ack_int(uint32_t irq_id, uint8_t irq_line_state);
|
||||
void ack_dma_int(uint32_t irq_id, uint8_t irq_line_state);
|
||||
|
||||
private:
|
||||
uint8_t imm_snd_regs[4]; // temporary storage for sound control registers
|
||||
@ -154,6 +165,9 @@ private:
|
||||
|
||||
uint8_t scsi_dma_cs = 0; // SCSI DMA control/status register value
|
||||
|
||||
uint8_t int_ctrl = 0;
|
||||
uint8_t dev_irq_lines = 0; // state of the IRQ lines
|
||||
|
||||
// AMIC subdevices instances
|
||||
std::unique_ptr<Ncr53C94> scsi;
|
||||
std::unique_ptr<EsccController> escc;
|
||||
|
@ -99,7 +99,7 @@ public:
|
||||
~HeathrowIC() = default;
|
||||
|
||||
bool supports_type(HWCompType type) {
|
||||
return type == HWCompType::MMIO_DEV;
|
||||
return (type == HWCompType::MMIO_DEV) || (type == HWCompType::INT_CTRL);
|
||||
};
|
||||
|
||||
/* PCI device methods */
|
||||
|
Loading…
x
Reference in New Issue
Block a user