mirror of
https://github.com/dingusdev/dingusppc.git
synced 2025-01-02 21:30:40 +00:00
Reworked interrupts for AMIC and Heathrow
This commit is contained in:
parent
9291a093d5
commit
fd6cc0f388
@ -45,6 +45,7 @@ ViaCuda::ViaCuda() {
|
||||
this->via_regs[VIA_DIRB] = 0;
|
||||
this->via_regs[VIA_DIRA] = 0;
|
||||
this->via_regs[VIA_IER] = 0;
|
||||
this->via_regs[VIA_SR] = 0;
|
||||
this->via_regs[VIA_ACR] = 0;
|
||||
this->via_regs[VIA_PCR] = 0;
|
||||
this->via_regs[VIA_IFR] = 0;
|
||||
@ -89,6 +90,20 @@ uint8_t ViaCuda::read(int reg) {
|
||||
case VIA_ANH:
|
||||
LOG_F(WARNING, "Attempted read from VIA Port A!");
|
||||
break;
|
||||
case VIA_T1CL:
|
||||
res = this->via_regs[VIA_T1CL];
|
||||
this->via_regs[VIA_IFR] &= ~IFR_T1;
|
||||
case VIA_T2CL:
|
||||
res = this->via_regs[VIA_T2CL];
|
||||
this->via_regs[VIA_IFR] &= ~IFR_T2;
|
||||
case VIA_SR:
|
||||
res = this->via_regs[VIA_SR];
|
||||
this->via_regs[VIA_IFR] &= ~IFR_SR;
|
||||
case VIA_IFR:
|
||||
res = this->via_regs[VIA_IFR];
|
||||
if (this->via_regs[VIA_IFR] & this->via_regs[VIA_IER])
|
||||
res |= 0x80;
|
||||
break;
|
||||
case VIA_IER:
|
||||
res |= 0x80; /* bit 7 always reads as "1" */
|
||||
}
|
||||
|
@ -72,6 +72,20 @@ enum {
|
||||
VIA_ANH = 0x0F, /* input/output register A, no handshake */
|
||||
};
|
||||
|
||||
/** IFR and IER register bits */
|
||||
enum {
|
||||
IER_SET = 0x80,
|
||||
IER_CLR = 0x00,
|
||||
|
||||
IFR_CA2 = 0x01,
|
||||
IFR_CA1 = 0x02,
|
||||
IFR_SR = 0x04,
|
||||
IFR_CB2 = 0x08,
|
||||
IFR_CB1 = 0x10,
|
||||
IFR_T2 = 0x20,
|
||||
IFR_T1 = 0x40,
|
||||
};
|
||||
|
||||
/** Cuda communication signals. */
|
||||
enum {
|
||||
CUDA_TIP = 0x20, /* transaction in progress: 0 - true, 1 - false */
|
||||
|
@ -68,50 +68,53 @@ bool AMIC::supports_type(HWCompType type) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//Interrupt Register
|
||||
void AMIC::process_interrupt(uint32_t cookie) {
|
||||
bool confirm_interrupt = false;
|
||||
uint32_t bit_field = 0;
|
||||
|
||||
if (this->int_ctrl_reg & 0x40) {
|
||||
confirm_interrupt = true;
|
||||
}
|
||||
switch (cookie) {
|
||||
case DEV_ID::PDM_HZTICK:
|
||||
case DEV_ID::VIA_CUDA:
|
||||
case DEV_ID::PDM_TIMER2:
|
||||
case DEV_ID::PDM_TIMER1:
|
||||
bit_field = (1 << VIA1_Interrupt);
|
||||
confirm_interrupt = true;
|
||||
break;
|
||||
case DEV_ID::NUBUS_SLOT3:
|
||||
case DEV_ID::NUBUS_SLOT0:
|
||||
case DEV_ID::NUBUS_SLOT1:
|
||||
case DEV_ID::NUBUS_SLOT2:
|
||||
case DEV_ID::SCSI0:
|
||||
case DEV_ID::SWIM3:
|
||||
case DEV_ID::SCSI1:
|
||||
bit_field = (1 << VIA2_Interrupt);
|
||||
confirm_interrupt = true;
|
||||
if (this->viacuda->read(VIA_IFR)) {
|
||||
bit_field = (1 << VIA1_Interrupt);
|
||||
confirm_interrupt = true;
|
||||
}
|
||||
else if (via2_slot_int_enable || via2_int_enable) {
|
||||
bit_field = (1 << VIA2_Interrupt);
|
||||
confirm_interrupt = true;
|
||||
}
|
||||
break;
|
||||
case DEV_ID::SCC_B:
|
||||
case DEV_ID::SCC_A:
|
||||
bit_field = (1 << SCC_Interrupt);
|
||||
confirm_interrupt = true;
|
||||
break;
|
||||
case DEV_ID::BMAC:
|
||||
case DEV_ID::ETHERNET:
|
||||
bit_field = (1 << Eth_Interrupt);
|
||||
confirm_interrupt = true;
|
||||
break;
|
||||
case DEV_ID::SCSI_DMA:
|
||||
case DEV_ID::Swim3_DMA:
|
||||
case DEV_ID::IDE0_DMA:
|
||||
case DEV_ID::IDE1_DMA:
|
||||
case DEV_ID::ETHERNET_DMA_OUT:
|
||||
case DEV_ID::ETHERNET_DMA_IN:
|
||||
case DEV_ID::SCC_A_DMA_OUT:
|
||||
case DEV_ID::SCC_A_DMA_IN:
|
||||
case DEV_ID::SCC_B_DMA_OUT:
|
||||
case DEV_ID::SCC_B_DMA_IN:
|
||||
if (dma_int_reg0) {
|
||||
bit_field = (1 << DMA_Interrupt);
|
||||
confirm_interrupt = true;
|
||||
}
|
||||
break;
|
||||
case DEV_ID::SOUND_DMA_OUT:
|
||||
case DEV_ID::SOUND_DMA_IN:
|
||||
case DEV_ID::PERCH_DMA:
|
||||
bit_field = (1 << DMA_Interrupt);
|
||||
confirm_interrupt = true;
|
||||
if (dma_int_reg1) {
|
||||
bit_field = (1 << DMA_Interrupt);
|
||||
confirm_interrupt = true;
|
||||
}
|
||||
break;
|
||||
case DEV_ID::NMI:
|
||||
bit_field = (1 << NMI_Interrupt);
|
||||
@ -125,9 +128,9 @@ void AMIC::process_interrupt(uint32_t cookie) {
|
||||
|
||||
uint32_t AMIC::ack_interrupt(uint32_t device_bits) {
|
||||
bool confirm_interrupt = false;
|
||||
bool ack_bit = this->int_mask1 & 0x80;
|
||||
bool ack_bit = this->int_ctrl_reg & 0x80;
|
||||
|
||||
if (device_bits & int_mask1)
|
||||
if (device_bits & this->int_ctrl_reg)
|
||||
confirm_interrupt = true;
|
||||
|
||||
if (confirm_interrupt && ack_bit)
|
||||
@ -143,9 +146,11 @@ uint32_t AMIC::read(uint32_t reg_start, uint32_t offset, int size) {
|
||||
switch(offset >> 12) {
|
||||
case 0: // VIA1 registers
|
||||
case 1:
|
||||
process_interrupt(VIA_CUDA);
|
||||
return this->viacuda->read(offset >> 9);
|
||||
case 4: // SCC registers
|
||||
this->escc->read_compat((offset >> 1) & 0xF);
|
||||
this->process_interrupt(SCC_A);
|
||||
return 0;
|
||||
case 0xA: // MACE registers
|
||||
return this->mace->read((offset >> 4) & 0xF);
|
||||
@ -180,7 +185,10 @@ uint32_t AMIC::read(uint32_t reg_start, uint32_t offset, int size) {
|
||||
case AMICReg::SCSI_DMA_Ctrl:
|
||||
return this->scsi_dma_cs;
|
||||
case AMICReg::Int_Ctrl:
|
||||
return this->int_mask1;
|
||||
if (this->int_ctrl_reg & 0x80) {
|
||||
ack_cpu_interrupt();
|
||||
}
|
||||
return this->int_ctrl_reg;
|
||||
default:
|
||||
LOG_F(WARNING, "Unknown AMIC register read, offset=%x", offset);
|
||||
}
|
||||
@ -253,6 +261,7 @@ void AMIC::write(uint32_t reg_start, uint32_t offset, uint32_t value, int size)
|
||||
return;
|
||||
case AMICReg::Snd_Out_DMA:
|
||||
this->snd_out_dma->write_dma_out_ctrl(value);
|
||||
this->dma_int_reg1 |= 0x2;
|
||||
this->process_interrupt(DEV_ID::SOUND_DMA_OUT);
|
||||
return;
|
||||
}
|
||||
@ -261,16 +270,22 @@ void AMIC::write(uint32_t reg_start, uint32_t offset, uint32_t value, int size)
|
||||
switch(offset) {
|
||||
case AMICReg::VIA2_Slot_IER:
|
||||
LOG_F(INFO, "AMIC VIA2 Slot Interrupt Enable Register updated, val=%x", value);
|
||||
via2_slot_int_enable = value;
|
||||
break;
|
||||
case AMICReg::VIA2_IER:
|
||||
LOG_F(INFO, "AMIC VIA2 Interrupt Enable Register updated, val=%x", value);
|
||||
via2_int_enable = value;
|
||||
break;
|
||||
case AMICReg::Video_Mode_Reg:
|
||||
LOG_F(INFO, "AMIC Video Mode Register set to %x", value);
|
||||
break;
|
||||
case AMICReg::Int_Ctrl:
|
||||
LOG_F(INFO, "AMIC Interrupt Control Register set to %X", value);
|
||||
this->int_mask1 = value;
|
||||
if (value & 0x80) {
|
||||
value &= 0xC0;
|
||||
ack_cpu_interrupt();
|
||||
}
|
||||
this->int_ctrl_reg = value;
|
||||
break;
|
||||
case AMICReg::DMA_Base_Addr_0:
|
||||
case AMICReg::DMA_Base_Addr_1:
|
||||
|
@ -95,13 +95,20 @@ enum AMICReg : uint32_t {
|
||||
Snd_Out_DMA = 0x14018, // sound output DMA status/control register
|
||||
|
||||
// VIA2 registers
|
||||
VIA2_Slot_INT = 0x26002,
|
||||
VIA2_Slot_IER = 0x26012,
|
||||
VIA2_INT = 0x26003,
|
||||
VIA2_IER = 0x26013,
|
||||
|
||||
// Video control registers
|
||||
Video_Mode_Reg = 0x28000,
|
||||
|
||||
|
||||
// Interrupt registers
|
||||
Int_Ctrl = 0x2A000,
|
||||
DMA_Int_0 = 0x2A008,
|
||||
Bus_Error_Int_0 = 0x2A009,
|
||||
DMA_Int_1 = 0x2A00A,
|
||||
Bus_Error_Int_1 = 0x2A00B,
|
||||
|
||||
// Undocumented diagnostics register
|
||||
Diag_Reg = 0x2C000,
|
||||
@ -132,6 +139,10 @@ enum AMICIntReg : uint32_t {
|
||||
ACK_Bit = 7,
|
||||
};
|
||||
|
||||
enum {
|
||||
FDC_PENDING = 0x40,
|
||||
};
|
||||
|
||||
/** Apple Memory-mapped I/O controller device. */
|
||||
class AMIC : public MMIODevice, public InterruptCtrl {
|
||||
public:
|
||||
@ -152,11 +163,16 @@ protected:
|
||||
private:
|
||||
uint8_t imm_snd_regs[4]; // temporary storage for sound control registers
|
||||
|
||||
uint32_t dma_base = 0; // DMA physical base address
|
||||
uint16_t snd_buf_size = 0; // sound buffer size in bytes
|
||||
uint8_t snd_out_ctrl = 0;
|
||||
uint32_t dma_base = 0; // DMA physical base address
|
||||
uint16_t snd_buf_size = 0; // sound buffer size in bytes
|
||||
uint8_t snd_out_ctrl = 0;
|
||||
|
||||
uint8_t scsi_dma_cs = 0; // SCSI DMA control/status register value
|
||||
uint8_t scsi_dma_cs = 0; // SCSI DMA control/status register value
|
||||
uint8_t int_ctrl_reg = 0;
|
||||
uint8_t dma_int_reg0 = 0;
|
||||
uint8_t dma_int_reg1 = 0;
|
||||
uint8_t via2_int_enable = 0;
|
||||
uint8_t via2_slot_int_enable = 0;
|
||||
|
||||
// AMIC subdevices instances
|
||||
std::unique_ptr<Ncr53C94> scsi;
|
||||
|
@ -161,9 +161,6 @@ uint32_t HeathrowIC::read(uint32_t reg_start, uint32_t offset, int size) {
|
||||
case 0x10:
|
||||
res = this->mesh->read((offset >> 4) & 0xF);
|
||||
break;
|
||||
case 0x11: // BMAC
|
||||
LOG_F(WARNING, "Attempted to read from BMAC: %x \n", (offset - 0x11000));
|
||||
break;
|
||||
case 0x12: // ESCC compatible
|
||||
return this->escc->read_compat((offset >> 4) & 0xF);
|
||||
case 0x13: // ESCC MacRISC
|
||||
@ -171,17 +168,10 @@ uint32_t HeathrowIC::read(uint32_t reg_start, uint32_t offset, int size) {
|
||||
case 0x14:
|
||||
res = this->screamer->snd_ctrl_read(offset - 0x14000, size);
|
||||
break;
|
||||
case 0x15: // BMAC
|
||||
LOG_F(WARNING, "Attempted to read from SWIM3: %x \n", (offset - 0x15000));
|
||||
break;
|
||||
case 0x16:
|
||||
case 0x17:
|
||||
res = this->viacuda->read((offset - 0x16000) >> 9);
|
||||
break;
|
||||
case 0x20: // IDE
|
||||
case 0x21:
|
||||
LOG_F(WARNING, "Attempted to read from IDE: %x \n", (offset - 0x20000));
|
||||
break;
|
||||
default:
|
||||
if (sub_addr >= 0x60) {
|
||||
res = this->nvram->read_byte((offset - 0x60000) >> 4);
|
||||
@ -209,9 +199,6 @@ void HeathrowIC::write(uint32_t reg_start, uint32_t offset, uint32_t value, int
|
||||
this->mesh->write((offset >> 4) & 0xF, value);
|
||||
this->process_interrupt(DEV_ID::SCSI0);
|
||||
break;
|
||||
case 0x11: // BMAC
|
||||
LOG_F(WARNING, "Attempted to write to BMAC: %x \n", (offset - 0x11000));
|
||||
break;
|
||||
case 0x12: // ESCC compatible
|
||||
this->escc->write_compat((offset >> 4) & 0xF, value);
|
||||
break;
|
||||
@ -222,18 +209,11 @@ void HeathrowIC::write(uint32_t reg_start, uint32_t offset, uint32_t value, int
|
||||
this->screamer->snd_ctrl_write(offset - 0x14000, value, size);
|
||||
this->process_interrupt(DEV_ID::DAVBUS);
|
||||
break;
|
||||
case 0x15: // SWIM 3
|
||||
LOG_F(WARNING, "Attempted to write to SWIM 3: %x \n", (offset - 0x15000));
|
||||
break;
|
||||
case 0x16:
|
||||
case 0x17:
|
||||
this->viacuda->write((offset - 0x16000) >> 9, value);
|
||||
this->process_interrupt(DEV_ID::VIA_CUDA);
|
||||
break;
|
||||
case 0x20: // IDE
|
||||
case 0x21:
|
||||
LOG_F(WARNING, "Attempted to write to IDE: %x \n", (offset - 0x20000));
|
||||
break;
|
||||
default:
|
||||
if (sub_addr >= 0x60) {
|
||||
this->nvram->write_byte((offset - 0x60000) >> 4, value);
|
||||
|
@ -27,41 +27,33 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
#include <memory>
|
||||
|
||||
enum DEV_ID {
|
||||
SCSI_DMA = 0,
|
||||
Swim3_DMA = 1,
|
||||
IDE0_DMA = 2,
|
||||
IDE1_DMA = 3,
|
||||
SCC_A_DMA_OUT = 4,
|
||||
SCC_A_DMA_IN = 5,
|
||||
SCC_B_DMA_OUT = 6,
|
||||
SCC_B_DMA_IN = 7,
|
||||
SOUND_DMA_OUT = 8,
|
||||
SOUND_DMA_IN = 9,
|
||||
VIDEO_OUT = 10,
|
||||
VIDEO_IN = 11,
|
||||
SCSI0 = 12,
|
||||
IDE0 = 13,
|
||||
IDE1 = 14,
|
||||
SCC_A = 15,
|
||||
SCC_B = 16,
|
||||
DAVBUS = 17,
|
||||
VIA_CUDA = 18,
|
||||
SWIM3 = 19,
|
||||
NMI = 20,
|
||||
PERCH_DMA = 21,
|
||||
PERCH = 22,
|
||||
BMAC_DMA_OUT = 23,
|
||||
BMAC_DMA_IN = 24,
|
||||
BMAC = 25,
|
||||
PDM_HZTICK = 26,
|
||||
PDM_TIMER2 = 27,
|
||||
PDM_TIMER1 = 28,
|
||||
SCSI1 = 29,
|
||||
NUBUS_SLOT3 = 30,
|
||||
NUBUS_SLOT0 = 31,
|
||||
NUBUS_SLOT1 = 32,
|
||||
NUBUS_SLOT2 = 33,
|
||||
PDM_VBL = 34,
|
||||
SCSI_DMA = 0,
|
||||
Swim3_DMA = 1,
|
||||
IDE0_DMA = 2,
|
||||
IDE1_DMA = 3,
|
||||
SCC_A_DMA_OUT = 4,
|
||||
SCC_A_DMA_IN = 5,
|
||||
SCC_B_DMA_OUT = 6,
|
||||
SCC_B_DMA_IN = 7,
|
||||
SOUND_DMA_OUT = 8,
|
||||
SOUND_DMA_IN = 9,
|
||||
VIDEO_OUT = 10,
|
||||
VIDEO_IN = 11,
|
||||
SCSI0 = 12,
|
||||
IDE0 = 13,
|
||||
IDE1 = 14,
|
||||
SCC_A = 15,
|
||||
SCC_B = 16,
|
||||
DAVBUS = 17,
|
||||
VIA_CUDA = 18,
|
||||
SWIM3 = 19,
|
||||
NMI = 20,
|
||||
PERCH_DMA = 21,
|
||||
PERCH = 22,
|
||||
ETHERNET_DMA_OUT = 23,
|
||||
ETHERNET_DMA_IN = 24,
|
||||
ETHERNET = 25,
|
||||
SCSI1 = 26,
|
||||
};
|
||||
|
||||
enum REG_ID {
|
||||
|
Loading…
Reference in New Issue
Block a user