diff --git a/devices/common/viacuda.cpp b/devices/common/viacuda.cpp index d560c93..22d63c9 100644 --- a/devices/common/viacuda.cpp +++ b/devices/common/viacuda.cpp @@ -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" */ } diff --git a/devices/common/viacuda.h b/devices/common/viacuda.h index 8a0cce4..5cde2ce 100644 --- a/devices/common/viacuda.h +++ b/devices/common/viacuda.h @@ -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 */ diff --git a/devices/ioctrl/amic.cpp b/devices/ioctrl/amic.cpp index 38dfdc0..44de97c 100644 --- a/devices/ioctrl/amic.cpp +++ b/devices/ioctrl/amic.cpp @@ -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: diff --git a/devices/ioctrl/amic.h b/devices/ioctrl/amic.h index 5a01f4e..da9feef 100644 --- a/devices/ioctrl/amic.h +++ b/devices/ioctrl/amic.h @@ -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 scsi; diff --git a/devices/ioctrl/heathrow.cpp b/devices/ioctrl/heathrow.cpp index 01f13d8..b4c6f98 100644 --- a/devices/ioctrl/heathrow.cpp +++ b/devices/ioctrl/heathrow.cpp @@ -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); diff --git a/devices/ioctrl/interruptctrl.h b/devices/ioctrl/interruptctrl.h index 4aebaa7..ec1c2d3 100644 --- a/devices/ioctrl/interruptctrl.h +++ b/devices/ioctrl/interruptctrl.h @@ -27,41 +27,33 @@ along with this program. If not, see . #include 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 {