diff --git a/devices/common/hwinterrupt.h b/devices/common/hwinterrupt.h index d897f42..b451af7 100644 --- a/devices/common/hwinterrupt.h +++ b/devices/common/hwinterrupt.h @@ -27,10 +27,11 @@ along with this program. If not, see . /** Enumerator for various interrupt sources. */ enum IntSrc : int { VIA_CUDA = 1, - VIA2 = 2, - SCC = 3, - ETHERNET = 4, - NMI = 5, + SCSI1 = 2, + SWIM3 = 3, + SCC = 4, + ETHERNET = 5, + NMI = 6, }; /** Base class for interrupt controllers. */ @@ -48,4 +49,4 @@ public: virtual void ack_dma_int(uint32_t irq_id, uint8_t irq_line_state) = 0; }; -#endif // HW_INTERRUPT_H \ No newline at end of file +#endif // HW_INTERRUPT_H diff --git a/devices/ioctrl/amic.cpp b/devices/ioctrl/amic.cpp index d998e0e..d1e7f5c 100644 --- a/devices/ioctrl/amic.cpp +++ b/devices/ioctrl/amic.cpp @@ -52,6 +52,8 @@ AMIC::AMIC() : MMIODevice() // register I/O devices this->scsi = std::unique_ptr (new Sc53C94()); + gMachineObj->add_subdevice("Curio_SCSI0", this->scsi.get()); + this->escc = std::unique_ptr (new EsccController()); this->mace = std::unique_ptr (new MaceController(MACE_ID)); this->viacuda = std::unique_ptr (new ViaCuda()); @@ -135,6 +137,12 @@ uint32_t AMIC::read(uint32_t reg_start, uint32_t offset, int size) switch(offset) { case AMICReg::Ariel_Config: return this->def_vid->get_vdac_config(); + case AMICReg::VIA2_IFR: + case AMICReg::VIA2_IFR_RBV: + return this->via2_ifr; + case AMICReg::VIA2_IER: + case AMICReg::VIA2_IER_RBV: + return this->via2_ier; case AMICReg::Video_Mode: return this->def_vid->get_video_mode(); case AMICReg::Monitor_Id: @@ -228,7 +236,11 @@ void AMIC::write(uint32_t reg_start, uint32_t offset, uint32_t value, int size) LOG_F(INFO, "AMIC VIA2 Slot Interrupt Enable Register updated, val=%x", value); break; case AMICReg::VIA2_IER: - LOG_F(INFO, "AMIC VIA2 Interrupt Enable Register updated, val=%x", value); + if (value & 0x80) { + this->via2_ier |= value & 0x7F; + } else { + this->via2_ier &= ~value; + } break; case AMICReg::Ariel_Clut_Index: this->def_vid->set_clut_index(value); @@ -313,6 +325,8 @@ uint32_t AMIC::register_dev_int(IntSrc src_id) { switch (src_id) { case IntSrc::VIA_CUDA: return 1; + case IntSrc::SCSI1: + return 0x800; default: ABORT_F("AMIC: unknown interrupt source %d", src_id); } @@ -325,6 +339,31 @@ uint32_t AMIC::register_dma_int(IntSrc src_id) { } void AMIC::ack_int(uint32_t irq_id, uint8_t irq_line_state) { + // dispatch AMIC interrupts from various sources + if (irq_id < 0x100) { + this->ack_cpu_int(irq_id, irq_line_state); + } else if (irq_id < 0x10000) { + this->ack_via2_int(irq_id >> 8, irq_line_state); + } else { + ABORT_F("AMIC: unknown interrupt source ID 0x%X", irq_id); + } +} + +void AMIC::ack_via2_int(uint32_t irq_id, uint8_t irq_line_state) { + if (irq_line_state) { + this->via2_ifr |= irq_id; + } else { + this->via2_ifr &= ~irq_id; + } + uint8_t new_irq = !!(this->via2_ifr & this->via2_ier & 0x7F); + this->via2_ifr = (this->via2_ifr & 0x7F) | (new_irq << 7); + if (new_irq != this->via2_irq) { + this->via2_irq = new_irq; + this->ack_cpu_int(2, new_irq); + } +} + +void AMIC::ack_cpu_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) { diff --git a/devices/ioctrl/amic.h b/devices/ioctrl/amic.h index c4eee6f..79c55b1 100644 --- a/devices/ioctrl/amic.h +++ b/devices/ioctrl/amic.h @@ -101,15 +101,18 @@ enum AMICReg : uint32_t { Snd_In_DMA = 0x14014, // sound input DMA status/control register Snd_Out_DMA = 0x14018, // sound output DMA status/control register - // VIA2 registers - VIA2_Slot_IER = 0x26012, - VIA2_IER = 0x26013, - // Video DAC (Ariel II) control registers Ariel_Clut_Index = 0x24000, Ariel_Clut_Color = 0x24001, Ariel_Config = 0x24002, + // VIA2 registers + VIA2_IFR = 0x26003, + VIA2_Slot_IER = 0x26012, + VIA2_IER = 0x26013, + VIA2_IFR_RBV = 0x27A03, // RBV-compatible mirror for the VIA2_IFR + VIA2_IER_RBV = 0x27C13, // RBV-compatible mirror for the VIA2_IER + // Video control registers Video_Mode = 0x28000, Pixel_Depth = 0x28001, @@ -155,6 +158,10 @@ public: 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); +protected: + void ack_via2_int(uint32_t irq_id, uint8_t irq_line_state); + void ack_cpu_int(uint32_t irq_id, uint8_t irq_line_state); + private: uint8_t imm_snd_regs[4]; // temporary storage for sound control registers @@ -167,6 +174,11 @@ private: uint8_t int_ctrl = 0; uint8_t dev_irq_lines = 0; // state of the IRQ lines + // pseudo VIA2 state + uint8_t via2_ier = 0; + uint8_t via2_ifr = 0; + uint8_t via2_irq = 0; + uint32_t pseudo_vbl_tid; // ID for the pseudo-VBL timer // AMIC subdevices instances